flat_kit 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +1 -2
  3. data/HISTORY.md +15 -0
  4. data/Manifest.txt +21 -26
  5. data/{bin → exe}/fk +2 -1
  6. data/flat_kit.gemspec +33 -0
  7. data/lib/flat_kit/cli.rb +48 -23
  8. data/lib/flat_kit/command/cat.rb +34 -32
  9. data/lib/flat_kit/command/merge.rb +37 -36
  10. data/lib/flat_kit/command/sort.rb +37 -37
  11. data/lib/flat_kit/command/stats.rb +96 -0
  12. data/lib/flat_kit/command.rb +10 -10
  13. data/lib/flat_kit/descendant_tracker.rb +17 -5
  14. data/lib/flat_kit/error.rb +4 -0
  15. data/lib/flat_kit/event_emitter.rb +7 -4
  16. data/lib/flat_kit/field_stats.rb +246 -0
  17. data/lib/flat_kit/field_type/boolean_type.rb +52 -0
  18. data/lib/flat_kit/field_type/date_type.rb +181 -0
  19. data/lib/flat_kit/field_type/float_type.rb +43 -0
  20. data/lib/flat_kit/field_type/guess_type.rb +23 -0
  21. data/lib/flat_kit/field_type/integer_type.rb +36 -0
  22. data/lib/flat_kit/field_type/null_type.rb +39 -0
  23. data/lib/flat_kit/field_type/string_type.rb +24 -0
  24. data/lib/flat_kit/field_type/timestamp_type.rb +48 -0
  25. data/lib/flat_kit/field_type/unknown_type.rb +30 -0
  26. data/lib/flat_kit/field_type.rb +83 -0
  27. data/lib/flat_kit/format.rb +11 -5
  28. data/lib/flat_kit/input/file.rb +11 -9
  29. data/lib/flat_kit/input/io.rb +18 -21
  30. data/lib/flat_kit/input.rb +8 -7
  31. data/lib/flat_kit/internal_node.rb +22 -19
  32. data/lib/flat_kit/jsonl/format.rb +6 -2
  33. data/lib/flat_kit/jsonl/reader.rb +7 -4
  34. data/lib/flat_kit/jsonl/record.rb +16 -19
  35. data/lib/flat_kit/jsonl/writer.rb +25 -18
  36. data/lib/flat_kit/jsonl.rb +8 -4
  37. data/lib/flat_kit/leaf_node.rb +6 -5
  38. data/lib/flat_kit/log_formatter.rb +20 -0
  39. data/lib/flat_kit/logger.rb +12 -19
  40. data/lib/flat_kit/merge.rb +21 -16
  41. data/lib/flat_kit/merge_tree.rb +5 -6
  42. data/lib/flat_kit/output/file.rb +13 -9
  43. data/lib/flat_kit/output/io.rb +40 -35
  44. data/lib/flat_kit/output.rb +12 -7
  45. data/lib/flat_kit/position.rb +18 -0
  46. data/lib/flat_kit/reader.rb +8 -8
  47. data/lib/flat_kit/record.rb +12 -12
  48. data/lib/flat_kit/sentinel_internal_node.rb +6 -5
  49. data/lib/flat_kit/sentinel_leaf_node.rb +4 -1
  50. data/lib/flat_kit/sort.rb +8 -9
  51. data/lib/flat_kit/stat_type/nominal_stats.rb +64 -0
  52. data/lib/flat_kit/stat_type/numerical_stats.rb +120 -0
  53. data/lib/flat_kit/stat_type/ordinal_stats.rb +37 -0
  54. data/lib/flat_kit/stat_type.rb +70 -0
  55. data/lib/flat_kit/stats.rb +64 -0
  56. data/lib/flat_kit/writer.rb +17 -3
  57. data/lib/flat_kit/xsv/format.rb +6 -2
  58. data/lib/flat_kit/xsv/reader.rb +8 -6
  59. data/lib/flat_kit/xsv/record.rb +21 -15
  60. data/lib/flat_kit/xsv/writer.rb +36 -18
  61. data/lib/flat_kit/xsv.rb +7 -4
  62. data/lib/flat_kit.rb +33 -21
  63. metadata +38 -113
  64. data/Rakefile +0 -20
  65. data/tasks/default.rake +0 -242
  66. data/tasks/extension.rake +0 -38
  67. data/tasks/man.rake +0 -7
  68. data/tasks/this.rb +0 -208
  69. data/test/device_dataset.rb +0 -117
  70. data/test/input/test_file.rb +0 -73
  71. data/test/input/test_io.rb +0 -93
  72. data/test/jsonl/test_format.rb +0 -22
  73. data/test/jsonl/test_reader.rb +0 -49
  74. data/test/jsonl/test_record.rb +0 -61
  75. data/test/jsonl/test_writer.rb +0 -68
  76. data/test/output/test_file.rb +0 -60
  77. data/test/output/test_io.rb +0 -104
  78. data/test/test_conversions.rb +0 -45
  79. data/test/test_event_emitter.rb +0 -72
  80. data/test/test_format.rb +0 -24
  81. data/test/test_helper.rb +0 -26
  82. data/test/test_merge.rb +0 -40
  83. data/test/test_merge_tree.rb +0 -64
  84. data/test/test_version.rb +0 -11
  85. data/test/xsv/test_format.rb +0 -22
  86. data/test/xsv/test_reader.rb +0 -61
  87. data/test/xsv/test_record.rb +0 -69
  88. data/test/xsv/test_writer.rb +0 -68
@@ -1,8 +1,12 @@
1
- require 'oj'
2
- require 'flat_kit/record'
1
+ # frozen_string_literal: true
2
+
3
+ require "oj"
4
+ require "flat_kit/record"
3
5
 
4
6
  module FlatKit
5
7
  module Jsonl
8
+ # Internal: Class that exposes data from a JSONL format record to the flatkit api
9
+ #
6
10
  class Record < ::FlatKit::Record
7
11
  attr_reader :compare_data
8
12
 
@@ -11,7 +15,7 @@ module FlatKit
11
15
  end
12
16
 
13
17
  def self.from_record(record)
14
- if record.instance_of?(FlatKit::Jsonl::Record) then
18
+ if record.instance_of?(FlatKit::Jsonl::Record)
15
19
 
16
20
  structured = record.complete_structured_data? ? record.complete_structured_data : nil
17
21
 
@@ -25,22 +29,20 @@ module FlatKit
25
29
  end
26
30
 
27
31
  def initialize(data:, compare_fields: :none,
28
- compare_data: Hash.new,
32
+ compare_data: {},
29
33
  complete_structured_data: nil)
30
34
  super(data: data, compare_fields: compare_fields)
31
35
 
32
36
  @complete_structured_data = complete_structured_data
33
37
 
34
- if complete_structured_data? && (compare_data.nil? || compare_data.empty?) then
35
- @compare_data = complete_structured_data
36
- else
37
- @compare_data = compare_data
38
- end
38
+ @compare_data = if complete_structured_data? && (compare_data.nil? || compare_data.empty?)
39
+ complete_structured_data
40
+ else
41
+ compare_data
42
+ end
39
43
 
40
44
  # only load compare data if it dosn't exist
41
- if data && compare_data.empty? then
42
- quick_parse
43
- end
45
+ quick_parse if data && compare_data.empty?
44
46
  end
45
47
 
46
48
  def [](key)
@@ -48,7 +50,7 @@ module FlatKit
48
50
  end
49
51
 
50
52
  def complete_structured_data
51
- @complete_structured_data ||= Oj.load(data)
53
+ @complete_structured_data ||= Oj.load(data, mode: :strict)
52
54
  end
53
55
  alias to_hash complete_structured_data
54
56
 
@@ -59,9 +61,7 @@ module FlatKit
59
61
  # overriding parent accessor since we may be initialized without raw bytes
60
62
  # to parse
61
63
  def data
62
- if @data.nil? && complete_structured_data? then
63
- @data = Oj.dump(complete_structured_data)
64
- end
64
+ @data = Oj.dump(complete_structured_data, mode: :json) if @data.nil? && complete_structured_data?
65
65
  @data
66
66
  end
67
67
  alias to_s data
@@ -79,6 +79,3 @@ module FlatKit
79
79
  end
80
80
  end
81
81
  end
82
-
83
-
84
-
@@ -1,19 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FlatKit
2
4
  module Jsonl
5
+ # Internal: Class that writes flatkit records to JSONL files
6
+ #
3
7
  class Writer < ::FlatKit::Writer
4
- attr_reader :output
5
- attr_reader :count
6
-
7
8
  def self.format_name
8
9
  ::FlatKit::Jsonl::Format.format_name
9
10
  end
10
11
 
11
- def initialize(destination:)
12
- super
13
- @output = ::FlatKit::Output.from(@destination)
14
- @count = 0
15
- end
16
-
12
+ # write the record and return the Position the record was written
13
+ #
17
14
  def write(record)
18
15
  case record
19
16
  when FlatKit::Jsonl::Record
@@ -24,21 +21,31 @@ module FlatKit
24
21
  else
25
22
  raise FlatKit::Error, "Unable to write records of type #{record.class}"
26
23
  end
27
- rescue FlatKit::Error => fe
28
- raise fe
29
- rescue => e
30
- ::FlatKit.logger.error "Error reading jsonl records from #{output.name}: #{e}"
24
+ rescue FlatKit::Error => e
25
+ raise e
26
+ rescue StandardError => e
27
+ ::FlatKit.logger.error "Error writing jsonl records to #{output.name}: #{e}"
31
28
  raise ::FlatKit::Error, e
32
29
  end
33
30
 
34
- def close
35
- @output.close
36
- end
37
-
38
31
  def write_record(record)
39
- # enforces ending in newlin if it doesn't already have one
32
+ # the index of the record being written is the same as the count of records written so far
33
+ record_index = @count
34
+
35
+ # get the current output stream position to calculate bytes written
36
+ start_offset = output.io.tell
37
+
38
+ # enforces ending in newline if it doesn't already have one
40
39
  output.io.puts record.to_s
40
+
41
+ ending_offset = output.io.tell
42
+ bytes_written = (ending_offset - start_offset)
43
+
41
44
  @count += 1
45
+
46
+ @last_position = ::FlatKit::Position.new(index: record_index,
47
+ offset: start_offset,
48
+ bytesize: bytes_written)
42
49
  end
43
50
  end
44
51
  end
@@ -1,8 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FlatKit
4
+ # Internal: Top level namespace for the newline-oriented JSON format
5
+ #
2
6
  module Jsonl
3
7
  end
4
8
  end
5
- require 'flat_kit/jsonl/record'
6
- require 'flat_kit/jsonl/reader'
7
- require 'flat_kit/jsonl/writer'
8
- require 'flat_kit/jsonl/format'
9
+ require "flat_kit/jsonl/record"
10
+ require "flat_kit/jsonl/reader"
11
+ require "flat_kit/jsonl/writer"
12
+ require "flat_kit/jsonl/format"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FlatKit
2
4
  # Private: The LeafNode is a wrapper around a Reader object to enable
3
5
  # a consistent api for use in the MergeTree
@@ -9,11 +11,9 @@ module FlatKit
9
11
  # If all the data is used up from the reader, it also notifies the next level
10
12
  # of that so the next level can remove it from the tree.
11
13
  class LeafNode
12
-
13
14
  include Comparable
14
15
 
15
- attr_reader :reader
16
- attr_reader :value
16
+ attr_reader :reader, :value
17
17
 
18
18
  attr_accessor :next_level
19
19
 
@@ -43,7 +43,7 @@ module FlatKit
43
43
 
44
44
  def update_and_replay
45
45
  self.next
46
- if finished? then
46
+ if finished?
47
47
  ::FlatKit.logger.debug "#{reader.source} has finished reading #{reader.count} records"
48
48
  next_level.player_finished(self)
49
49
  end
@@ -65,7 +65,8 @@ module FlatKit
65
65
 
66
66
  def <=>(other)
67
67
  return -1 if other.sentinel?
68
- self.value.<=>(other.value)
68
+
69
+ value <=> (other.value)
69
70
  end
70
71
  end
71
72
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+
5
+ module FlatKit
6
+ # Internal: Log formatting class for FlatKit
7
+ #
8
+ class LogFormatter < ::Logger::Formatter
9
+ FORMAT = "%s %5d %05s : %s\n"
10
+ DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
11
+ def initialize
12
+ super
13
+ self.datetime_format = DATETIME_FORMAT
14
+ end
15
+
16
+ def call(severity, time, _progname, msg)
17
+ format(FORMAT, format_datetime(time.utc), Process.pid, severity, msg2str(msg))
18
+ end
19
+ end
20
+ end
@@ -1,19 +1,12 @@
1
- require 'logger'
1
+ # frozen_string_literal: true
2
2
 
3
- module FlatKit
4
- class LogFormatter < ::Logger::Formatter
5
- FORMAT = "%s %5d %05s : %s\n".freeze
6
- DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ".freeze
7
- def initialize
8
- super
9
- self.datetime_format = DATETIME_FORMAT
10
- end
11
-
12
- def call(severity, time, progname, msg)
13
- FORMAT % [format_datetime(time.utc), Process.pid, severity, msg2str(msg)]
14
- end
15
- end
3
+ require "logger"
16
4
 
5
+ # Public: Top level namespace for the gem
6
+ #
7
+ module FlatKit
8
+ # Internal: Logger class
9
+ #
17
10
  class Logger
18
11
  def self.for_io(io)
19
12
  ::Logger.new(io, formatter: LogFormatter.new)
@@ -26,11 +19,11 @@ module FlatKit
26
19
  end
27
20
 
28
21
  def self.log_to(destination = $stderr)
29
- if destination.kind_of?(::IO) then
30
- @logger = ::FlatKit::Logger.for_io(destination)
31
- else
32
- @logger = ::FlatKit::Logger.for_path(destination)
33
- end
22
+ @logger = if destination.is_a?(::IO)
23
+ ::FlatKit::Logger.for_io(destination)
24
+ else
25
+ ::FlatKit::Logger.for_path(destination)
26
+ end
34
27
  end
35
28
 
36
29
  def self.logger
@@ -1,15 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FlatKit
4
+ # Internal: Class implementing merging from N inputs and output to 1 output.
5
+ #
2
6
  class Merge
3
-
4
7
  include ::FlatKit::EventEmitter
5
8
 
6
- attr_reader :readers
7
- attr_reader :writer
8
- attr_reader :compare_fields
9
+ attr_reader :readers, :writer, :compare_fields
9
10
 
10
- def initialize(inputs:, input_fallback: "auto",
11
- output:, output_fallback: "auto",
12
- compare_fields:)
11
+ def initialize(inputs:, output:, compare_fields:, input_fallback: "auto", output_fallback: "auto")
13
12
  @compare_fields = compare_fields
14
13
  @readers = ::FlatKit::Reader.create_readers_from_paths(paths: inputs, compare_fields: @compare_fields,
15
14
  fallback: input_fallback)
@@ -19,19 +18,12 @@ module FlatKit
19
18
 
20
19
  def call
21
20
  ::FlatKit.logger.debug "Merging the following files into #{writer.destination}"
22
- ::FlatKit.logger.debug "Using this key for sorting: #{compare_fields.join(", ")}"
21
+ ::FlatKit.logger.debug "Using this key for sorting: #{compare_fields.join(', ')}"
23
22
  readers.each do |r|
24
23
  ::FlatKit.logger.debug " #{r.source}"
25
24
  end
26
25
 
27
- merge_tree = ::FlatKit::MergeTree.new(readers)
28
-
29
- notify_listeners(name: :start, data: :start)
30
- merge_tree.each do |record|
31
- writer.write(record)
32
- notify_listeners(name: :record, data: record)
33
- end
34
- notify_listeners(name: :stop, data: :stop)
26
+ run_merge(readers)
35
27
 
36
28
  readers.each do |r|
37
29
  ::FlatKit.logger.debug " #{r.source} produced #{r.count} records"
@@ -40,5 +32,18 @@ module FlatKit
40
32
  writer.close
41
33
  ::FlatKit.logger.debug "Wrote #{writer.count} records to #{writer.destination}"
42
34
  end
35
+
36
+ private
37
+
38
+ def run_merge(readers)
39
+ tree = ::FlatKit::MergeTree.new(readers)
40
+ notify_listeners(name: :start, data: :start)
41
+ tree.each do |record|
42
+ position = writer.write(record)
43
+ meta = { position: position }
44
+ notify_listeners(name: :record, data: record, meta: meta)
45
+ end
46
+ notify_listeners(name: :stop, data: :stop)
47
+ end
43
48
  end
44
49
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FlatKit
2
4
  # Public: Merge a list of sorted records from Readers into a single output Writer
3
5
  #
@@ -29,9 +31,7 @@ module FlatKit
29
31
  class MergeTree
30
32
  include Enumerable
31
33
 
32
- attr_reader :leaves
33
- attr_reader :levels
34
- attr_reader :readers
34
+ attr_reader :leaves, :levels, :readers
35
35
 
36
36
  def initialize(readers)
37
37
  @readers = readers
@@ -44,9 +44,7 @@ module FlatKit
44
44
 
45
45
  # Need to pad the leaves to an even number so that the slicing by 2 for
46
46
  # the tournament will work
47
- if @leaves.size.odd? then
48
- @leaves << SentinelLeafNode.new
49
- end
47
+ @leaves << SentinelLeafNode.new if @leaves.size.odd?
50
48
 
51
49
  init_tree
52
50
  end
@@ -94,6 +92,7 @@ module FlatKit
94
92
  def each
95
93
  loop do
96
94
  break if root.leaf.finished?
95
+
97
96
  yield root.value
98
97
  # consume the yielded value and have the tournament tree replay those
99
98
  # brackets affected
@@ -1,22 +1,31 @@
1
- require 'zlib'
1
+ # frozen_string_literal: true
2
+
3
+ require "zlib"
4
+ require "pathname"
2
5
 
3
6
  module FlatKit
4
7
  class Output
8
+ # Internal: File output implementation
9
+ #
5
10
  class File < Output
6
11
  attr_reader :path
7
12
 
13
+ # internal api method for testing purposes
14
+ attr_reader :io
15
+
8
16
  def self.handles?(obj)
9
17
  return true if obj.instance_of?(Pathname)
10
18
  return false unless obj.instance_of?(String)
11
19
 
12
20
  # incase these get loaded in different orders
13
- return false if ::FlatKit::Output::IO.is_stdout?(obj)
14
- return false if ::FlatKit::Output::IO.is_stderr?(obj)
21
+ return false if ::FlatKit::Output::IO.stdout?(obj)
22
+ return false if ::FlatKit::Output::IO.stderr?(obj)
15
23
 
16
- return true
24
+ true
17
25
  end
18
26
 
19
27
  def initialize(obj)
28
+ super()
20
29
  @path = Pathname.new(obj)
21
30
  path.dirname.mkpath
22
31
  @io = open_output(path)
@@ -30,11 +39,6 @@ module FlatKit
30
39
  @io.close
31
40
  end
32
41
 
33
- # internal api method for testing purposes
34
- def io
35
- @io
36
- end
37
-
38
42
  private
39
43
 
40
44
  # open the opropriate otuput type depending on the destination file name
@@ -1,73 +1,78 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FlatKit
2
4
  class Output
5
+ # Internal: Non-file Output impelementation - this is genrally to stdout or stderr
6
+ #
3
7
  class IO < Output
4
- attr_reader :count
8
+ attr_reader :count, :name
9
+
10
+ # internal api method for testing
11
+ attr_reader :io
5
12
 
6
- STDOUTS = %w[ stdout STDOUT - <stdout> ]
7
- STDERRS = %w[ stderr STDERR <stderr> ]
13
+ STDOUTS = %w[stdout STDOUT - <stdout>].freeze
14
+ STDERRS = %w[stderr STDERR <stderr>].freeze
8
15
 
9
16
  def self.handles?(obj)
10
- return true if is_stderr?(obj)
11
- return true if is_stdout?(obj)
12
- return true if [ ::File, ::StringIO, ::IO ].any? { |klass| obj.kind_of?(klass) }
13
- return false
17
+ return true if stderr?(obj)
18
+ return true if stdout?(obj)
19
+ return true if [::File, ::StringIO, ::IO].any? { |klass| obj.is_a?(klass) }
20
+
21
+ false
14
22
  end
15
23
 
16
- def self.is_stderr?(obj)
24
+ def self.stderr?(obj)
17
25
  case obj
18
26
  when String
19
27
  return true if STDERRS.include?(obj)
20
28
  when ::IO
21
- return true if obj == ::STDERR
29
+ return true if obj == $stderr
22
30
  end
23
- return false
31
+ false
24
32
  end
25
33
 
26
- def self.is_stdout?(obj)
34
+ def self.stdout?(obj)
27
35
  case obj
28
36
  when String
29
37
  return true if STDOUTS.include?(obj)
30
38
  when ::IO
31
- return true if obj == ::STDOUT
39
+ return true if obj == $stdout
32
40
  end
33
- return false
41
+ false
34
42
  end
35
43
 
36
44
  def initialize(obj)
45
+ super()
37
46
  @count = 0
38
- if self.class.is_stdout?(obj) then
47
+ @name = nil
48
+ @io = nil
49
+ init_name_and_io(obj)
50
+ end
51
+
52
+ # this goes to an io stream and we are not in charge of opening it
53
+ def close
54
+ @io.close
55
+ end
56
+
57
+ private
58
+
59
+ def init_name_and_io(obj)
60
+ if self.class.stdout?(obj)
39
61
  @name = "<STDOUT>"
40
62
  @io = $stdout
41
- elsif self.class.is_stderr?(obj) then
63
+ elsif self.class.stderr?(obj)
42
64
  @name = "<STDERR>"
43
65
  @io = $stderr
44
- elsif obj.kind_of?(::File) then
45
- @name = obj.path
66
+ elsif obj.is_a?(::IO)
67
+ @name = (obj.respond_to?(:path) && obj.path) || obj.inspect
46
68
  @io = obj
47
- elsif obj.kind_of?(::StringIO) then
48
- @name = obj.inspect
49
- @io = obj
50
- elsif obj.kind_of?(::IO) then
69
+ elsif obj.is_a?(::StringIO)
51
70
  @name = obj.inspect
52
71
  @io = obj
53
72
  else
54
73
  raise ::FlatKit::Error, "Unable to create #{self.class} from #{obj.class} : #{obj.inspect}"
55
74
  end
56
75
  end
57
-
58
- def name
59
- @name
60
- end
61
-
62
- # this goes to an io stream and we are not in charge of opening it
63
- def close
64
- @io.close
65
- end
66
-
67
- # internal api method for testing
68
- def io
69
- @io
70
- end
71
76
  end
72
77
  end
73
78
  end
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FlatKit
4
+ # Internal: Base clases for all output handlers
5
+ #
2
6
  class Output
3
7
  extend DescendantTracker
4
8
 
5
9
  def self.from(out)
6
- return out if out.kind_of?(::FlatKit::Output)
10
+ return out if out.is_a?(::FlatKit::Output)
7
11
 
8
12
  out_klass = find_child(:handles?, out)
9
- if out_klass then
10
- return out_klass.new(out)
11
- end
13
+ return out_klass.new(out) if out_klass
12
14
 
13
15
  raise FlatKit::Error, "Unable to create output from #{out.class} : #{out.inspect}"
14
16
  end
@@ -17,16 +19,19 @@ module FlatKit
17
19
  raise NotImplementedError, "#{self.class} must implement #name"
18
20
  end
19
21
 
20
- #
21
22
  def io
22
23
  raise NotImplementedError, "#{self.class} must implement #io"
23
24
  end
24
25
 
26
+ def tell
27
+ io.tell
28
+ end
29
+
25
30
  def close
26
31
  raise NotImplementedError, "#{self.class} must implement #close"
27
32
  end
28
33
  end
29
34
  end
30
35
 
31
- require 'flat_kit/output/io'
32
- require 'flat_kit/output/file'
36
+ require "flat_kit/output/io"
37
+ require "flat_kit/output/file"
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlatKit
4
+ # The information about the position of a record in an IO stream
5
+ #
6
+ # Generally this is going to be returned by a write_record method to return
7
+ # information about the record that was just written
8
+ #
9
+ class Position
10
+ attr_reader :index, :offset, :bytesize # zero based # byte offset in the IO stream # byte length of the record
11
+
12
+ def initialize(index: nil, offset: nil, bytesize: nil)
13
+ @index = index
14
+ @offset = offset
15
+ @bytesize = bytesize
16
+ end
17
+ end
18
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FlatKit
2
4
  # Public: the base class for all format readers.
3
5
  #
@@ -14,24 +16,21 @@ module FlatKit
14
16
  # API:
15
17
  #
16
18
  # initialize(source:, compare_fields:)
17
- # each -> Yields / returns
19
+ # each -> Yields / returns
18
20
  #
19
21
  class Reader
20
22
  include Enumerable
21
23
 
22
- attr_reader :source
23
- attr_reader :compare_fields
24
+ attr_reader :source, :compare_fields
24
25
 
25
26
  def self.create_reader_from_path(path: "-", fallback: "auto", compare_fields: :none)
26
27
  format = ::FlatKit::Format.for_with_fallback!(path: path, fallback: fallback)
27
- return format.reader.new(source: path, compare_fields: compare_fields)
28
+ format.reader.new(source: path, compare_fields: compare_fields)
28
29
  end
29
30
 
30
31
  def self.create_readers_from_paths(paths:, fallback: "auto", compare_fields: :none)
31
32
  # default to stdin if there are no paths
32
- if paths.empty? then
33
- paths << "-"
34
- end
33
+ paths << "-" if paths.empty?
35
34
 
36
35
  paths.map do |path|
37
36
  create_reader_from_path(path: path, fallback: fallback, compare_fields: compare_fields)
@@ -55,7 +54,8 @@ module FlatKit
55
54
 
56
55
  def resolve_compare_fields(value)
57
56
  return [] if value == :none
58
- return value
57
+
58
+ value
59
59
  end
60
60
  end
61
61
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FlatKit
2
4
  # Public: The base class that all record classes should inherit from.
3
5
  #
@@ -35,11 +37,9 @@ module FlatKit
35
37
  # # the initialize method must call super(data:, compare_fields:) to
36
38
  # initializa the root data structures
37
39
  class Record
38
-
39
40
  include Comparable
40
41
 
41
- attr_reader :data
42
- attr_reader :compare_fields
42
+ attr_reader :data, :compare_fields
43
43
 
44
44
  def initialize(data:, compare_fields:)
45
45
  @data = data
@@ -57,15 +57,15 @@ module FlatKit
57
57
  my_val = self[field]
58
58
  other_val = other[field]
59
59
 
60
- if my_val.nil? && other_val.nil? then
61
- compare_result = 0
62
- elsif my_val.nil?
63
- compare_result = -1
64
- elsif other_val.nil?
65
- compare_result = 1
66
- else
67
- compare_result = my_val.<=>(other_val)
68
- end
60
+ compare_result = if my_val.nil? && other_val.nil?
61
+ 0
62
+ elsif my_val.nil?
63
+ -1
64
+ elsif other_val.nil?
65
+ 1
66
+ else
67
+ my_val <=> (other_val)
68
+ end
69
69
 
70
70
  return compare_result unless compare_result.zero?
71
71
  end