From 6b22a09070c2c7c4bf0c526e5acd6918b6d9026a Mon Sep 17 00:00:00 2001 From: Jasveen Date: Mon, 28 Oct 2024 17:07:47 +0900 Subject: [PATCH 1/6] Add TSV class --- lib/csv.rb | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/lib/csv.rb b/lib/csv.rb index f6eb32a6..3aa96ad5 100644 --- a/lib/csv.rb +++ b/lib/csv.rb @@ -2129,6 +2129,92 @@ def initialize(data, writer if @writer_options[:write_headers] end + class TSV < CSV + def initialize(data, **options) + options = options.dup + if !options.key?(:col_sep) && !options.key?(:sep) + options[:col_sep] = "\t" + end + super(data, **options) + end + + class << self + def foreach(path, mode="r", **options, &block) + options = options.dup + if !options.key?(:col_sep) && !options.key?(:sep) + options[:col_sep] = "\t" + end + CSV.foreach(path, mode, **options, &block) + end + + def read(path, **options) + options = options.dup + if !options.key?(:col_sep) && !options.key?(:sep) + options[:col_sep] = "\t" + end + CSV.read(path, **options) + end + + def parse(str, **options) + options = options.dup + if !options.key?(:col_sep) && !options.key?(:sep) + options[:col_sep] = "\t" + end + CSV.parse(str, **options) + end + + def generate(str = nil, **options) + options = with_default_separator(options) + CSV.generate(str, **options) + end + + def open(filename, mode="rb", **options, &block) + options = with_default_separator(options) + CSV.open(filename, mode, **options, &block) + end + + def table(path, **options) + options = with_default_separator(options) + CSV.table(path, **options) + end + + def parse_line(line, **options) + options = with_default_separator(options) + CSV.parse_line(line, **options) + end + + def generate_line(row, **options) + options = with_default_separator(options) + CSV.generate_line(row, **options) + end + + def instance(data = nil, **options, &block) + options = with_default_separator(options) + CSV.instance(data, **options, &block) + end + + def filter(input=nil, output=nil, **options, &block) + options = with_default_separator(options) + CSV.filter(input, output, **options, &block) + end + + def readlines(path, **options) + options = with_default_separator(options) + CSV.readlines(path, **options) + end + + private + + def with_default_separator(options) + options = options.dup + if !options.key?(:col_sep) && !options.key?(:sep) + options[:col_sep] = "\t" + end + options + end + end + end + # :call-seq: # csv.col_sep -> string # From 3414adbba2639819e0063d25a2739fc9edf52caa Mon Sep 17 00:00:00 2001 From: Jasveen Date: Wed, 30 Oct 2024 22:32:40 +0900 Subject: [PATCH 2/6] Simplify CSV::TSV implementation to only override initialize --- lib/csv.rb | 82 +----------------------------------------------------- 1 file changed, 1 insertion(+), 81 deletions(-) diff --git a/lib/csv.rb b/lib/csv.rb index 3aa96ad5..cfe42911 100644 --- a/lib/csv.rb +++ b/lib/csv.rb @@ -2131,87 +2131,7 @@ def initialize(data, class TSV < CSV def initialize(data, **options) - options = options.dup - if !options.key?(:col_sep) && !options.key?(:sep) - options[:col_sep] = "\t" - end - super(data, **options) - end - - class << self - def foreach(path, mode="r", **options, &block) - options = options.dup - if !options.key?(:col_sep) && !options.key?(:sep) - options[:col_sep] = "\t" - end - CSV.foreach(path, mode, **options, &block) - end - - def read(path, **options) - options = options.dup - if !options.key?(:col_sep) && !options.key?(:sep) - options[:col_sep] = "\t" - end - CSV.read(path, **options) - end - - def parse(str, **options) - options = options.dup - if !options.key?(:col_sep) && !options.key?(:sep) - options[:col_sep] = "\t" - end - CSV.parse(str, **options) - end - - def generate(str = nil, **options) - options = with_default_separator(options) - CSV.generate(str, **options) - end - - def open(filename, mode="rb", **options, &block) - options = with_default_separator(options) - CSV.open(filename, mode, **options, &block) - end - - def table(path, **options) - options = with_default_separator(options) - CSV.table(path, **options) - end - - def parse_line(line, **options) - options = with_default_separator(options) - CSV.parse_line(line, **options) - end - - def generate_line(row, **options) - options = with_default_separator(options) - CSV.generate_line(row, **options) - end - - def instance(data = nil, **options, &block) - options = with_default_separator(options) - CSV.instance(data, **options, &block) - end - - def filter(input=nil, output=nil, **options, &block) - options = with_default_separator(options) - CSV.filter(input, output, **options, &block) - end - - def readlines(path, **options) - options = with_default_separator(options) - CSV.readlines(path, **options) - end - - private - - def with_default_separator(options) - options = options.dup - if !options.key?(:col_sep) && !options.key?(:sep) - options[:col_sep] = "\t" - end - options - end + super(data, **({col_sep: "\t"}.merge(options))) end end From a5504e3d6961cd7b2a00265bd55c0893e9ee781c Mon Sep 17 00:00:00 2001 From: Jasveen Date: Thu, 14 Nov 2024 15:12:54 +0900 Subject: [PATCH 3/6] Add TSV tests and fix test runner --- run-test.rb | 26 +++++++++++++++++++++++++- test/csv/test_tsv.rb | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 test/csv/test_tsv.rb diff --git a/run-test.rb b/run-test.rb index 8c2641d9..c8d82465 100755 --- a/run-test.rb +++ b/run-test.rb @@ -1,14 +1,38 @@ #!/usr/bin/env ruby +# Disable Ractor experimental warning +Warning[:experimental] = false + $VERBOSE = true $LOAD_PATH.unshift("test") $LOAD_PATH.unshift("test/lib") $LOAD_PATH.unshift("lib") +require "test/unit" + +# Configure test-unit for better stability +Test::Unit::AutoRunner.need_auto_run = false + +# Track test execution status +failed_tests = [] + Dir.glob("test/csv/**/*test_*.rb") do |test_rb| # Ensure we only load syntax that we can handle next if RUBY_VERSION < "2.7" && test_rb.end_with?("test_patterns.rb") - require File.expand_path(test_rb) + begin + require File.expand_path(test_rb) + rescue => e + puts "Error loading #{test_rb}: #{e.message}" + puts e.backtrace + failed_tests << test_rb + end end + +# Run tests with custom configuration +runner = Test::Unit::AutoRunner.new(true) +runner.process_args([]) + +# Exit with failure if any tests failed +exit(failed_tests.empty? && runner.run ? 0 : 1) diff --git a/test/csv/test_tsv.rb b/test/csv/test_tsv.rb new file mode 100644 index 00000000..77229c09 --- /dev/null +++ b/test/csv/test_tsv.rb @@ -0,0 +1,32 @@ +require_relative "helper" + +class TestTSV < Test::Unit::TestCase + def test_default_separator + tsv = TSV.new(String.new) + assert_equal("\t", tsv.col_sep) + end + + def test_override_separator + tsv = TSV.new(String.new, col_sep: ",") + assert_equal(",", tsv.col_sep) + end + + def test_read_tsv_data + data = "a\tb\tc\n1\t2\t3" + result = TSV.parse(data) + assert_equal([["a", "b", "c"], ["1", "2", "3"]], result.to_a) + end + + def test_write_tsv_data + output = String.new + TSV.generate(output) do |tsv| + tsv << ["a", "b", "c"] + tsv << ["1", "2", "3"] + end + assert_equal("a\tb\tc\n1\t2\t3\n", output) + end + + def test_inheritance + assert_kind_of(CSV, TSV.new(String.new)) + end +end From e1b962a1f908f0114de8f2b75d728d5f91ac2281 Mon Sep 17 00:00:00 2001 From: Jasveen Date: Thu, 14 Nov 2024 15:39:38 +0900 Subject: [PATCH 4/6] Revert run-test.rb changes - will address Ractor warnings separately --- run-test.rb | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/run-test.rb b/run-test.rb index c8d82465..8c2641d9 100755 --- a/run-test.rb +++ b/run-test.rb @@ -1,38 +1,14 @@ #!/usr/bin/env ruby -# Disable Ractor experimental warning -Warning[:experimental] = false - $VERBOSE = true $LOAD_PATH.unshift("test") $LOAD_PATH.unshift("test/lib") $LOAD_PATH.unshift("lib") -require "test/unit" - -# Configure test-unit for better stability -Test::Unit::AutoRunner.need_auto_run = false - -# Track test execution status -failed_tests = [] - Dir.glob("test/csv/**/*test_*.rb") do |test_rb| # Ensure we only load syntax that we can handle next if RUBY_VERSION < "2.7" && test_rb.end_with?("test_patterns.rb") - begin - require File.expand_path(test_rb) - rescue => e - puts "Error loading #{test_rb}: #{e.message}" - puts e.backtrace - failed_tests << test_rb - end + require File.expand_path(test_rb) end - -# Run tests with custom configuration -runner = Test::Unit::AutoRunner.new(true) -runner.process_args([]) - -# Exit with failure if any tests failed -exit(failed_tests.empty? && runner.run ? 0 : 1) From afea0325681023e0c997935f915a4ab7ba906e0e Mon Sep 17 00:00:00 2001 From: Jas Date: Thu, 14 Nov 2024 16:08:41 +0900 Subject: [PATCH 5/6] Update test/csv/test_tsv.rb Co-authored-by: Sutou Kouhei --- test/csv/test_tsv.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/csv/test_tsv.rb b/test/csv/test_tsv.rb index 77229c09..1304dd62 100644 --- a/test/csv/test_tsv.rb +++ b/test/csv/test_tsv.rb @@ -2,7 +2,7 @@ class TestTSV < Test::Unit::TestCase def test_default_separator - tsv = TSV.new(String.new) + tsv = CSV::TSV.new(String.new) assert_equal("\t", tsv.col_sep) end From d08ebc64f7a0b05f3355bfc68bea8617271c0f53 Mon Sep 17 00:00:00 2001 From: jsxs Date: Mon, 25 Nov 2024 13:45:55 +0900 Subject: [PATCH 6/6] Update TSV class references --- test/csv/test_tsv.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/csv/test_tsv.rb b/test/csv/test_tsv.rb index 1304dd62..81a6edee 100644 --- a/test/csv/test_tsv.rb +++ b/test/csv/test_tsv.rb @@ -7,19 +7,19 @@ def test_default_separator end def test_override_separator - tsv = TSV.new(String.new, col_sep: ",") + tsv = CSV::TSV.new(String.new, col_sep: ",") assert_equal(",", tsv.col_sep) end def test_read_tsv_data data = "a\tb\tc\n1\t2\t3" - result = TSV.parse(data) + result = CSV::TSV.parse(data) assert_equal([["a", "b", "c"], ["1", "2", "3"]], result.to_a) end def test_write_tsv_data output = String.new - TSV.generate(output) do |tsv| + CSV::TSV.generate(output) do |tsv| tsv << ["a", "b", "c"] tsv << ["1", "2", "3"] end @@ -27,6 +27,6 @@ def test_write_tsv_data end def test_inheritance - assert_kind_of(CSV, TSV.new(String.new)) + assert_kind_of(CSV, CSV::TSV.new(String.new)) end end