smarter_csv 1.9.0 → 1.9.2.pre01

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 20db4a75108d2b7934b90e6d0e3fef3053e61ad077b4ec4966a97a6e5cb3aa42
4
- data.tar.gz: 44d1c3b995b3f7d53d46768437517379dfe3b93fa1db1384054ac16baadfb8d6
3
+ metadata.gz: 75d9d441d771c2fbe0861e0bc5f84dbf05d010b4844a867fc4679df002822d07
4
+ data.tar.gz: 0d5d37d4f2654fd354a2adac23019b2955540c1356c57f72052c01220598ffa2
5
5
  SHA512:
6
- metadata.gz: 74a2edab893bd9e1b798b03321aea55b566accb92a47d939bdddb616af57fc8525b60b50fb94d1f67face95c83d0a00300f587355dd4934130f5bac9879d5dcd
7
- data.tar.gz: 1cb78471b4021dafed4fc1bdd42c2acae934eb1a89f05e9700bfb99f40543c770db58b9b42a70272de9797bdf43fe5d53fa8c352964c1574d658ab2f881a06d6
6
+ metadata.gz: b24e2b09ea919994da347eb52b781868a19e0f28dc367bfeb43b8a254619ab8dd882d3035f0546683c2ebc893fd600ce05a3abb800e4b124c7369d314607ee3f
7
+ data.tar.gz: 3a1115ac4937c2fedf469d1f45e3aa1cf7ed03f1f55d66f6cb310c767a3b5e8cb4966a19ba968f065c5d1de2d7074f479b5eeb0686dbab8012e5e6b8ed0f2628
data/CHANGELOG.md CHANGED
@@ -1,6 +1,19 @@
1
1
 
2
2
  # SmarterCSV 1.x Change Log
3
3
 
4
+ ## 1.9.2.pre01 (2023-11-11)
5
+ * fixed bug with '\\' at end of line (issue #252)
6
+ * fixed require statements
7
+
8
+ ## 1.9.1 (2023-10-30) (YANKED)
9
+ * yanked
10
+ * no functional changes
11
+ * refactored directory structure
12
+ * re-added JRuby and TruffleRuby to CI tests
13
+ * no C-accelleration for JRuby
14
+ * refactored options parsing
15
+ * code coverage / rubocop
16
+
4
17
  ## 1.9.0 (2023-09-04)
5
18
  * fixed issue #139
6
19
 
data/Gemfile CHANGED
@@ -5,10 +5,13 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in smarter_csv.gemspec
6
6
  gemspec
7
7
 
8
- gem "rake" # , "< 11"
8
+ gem "rake"
9
9
  gem "rake-compiler"
10
10
 
11
11
  gem 'pry'
12
-
13
- gem "rspec"
14
12
  gem "rubocop"
13
+
14
+ group :test do
15
+ gem "rspec"
16
+ gem "simplecov"
17
+ end
data/README.md CHANGED
@@ -46,7 +46,11 @@ One `smarter_csv` user wrote:
46
46
  * able to ignore "columns" in the input (delete columns)
47
47
  * able to eliminate nil or empty fields from the result hashes (default)
48
48
 
49
- NOTE; This Gem is only for importing CSV files - writing of CSV files is not supported at this time.
49
+ #### Assumptions / Limitations
50
+ * It is assumed that the escape character is `\`, as on UNIX and Windows systems.
51
+ * It is assumed that quote charcters around fields are balanced, e.g. valid: `"field"`, invalid: `"field\"`
52
+ e.g. an escaped `quote_char` does not denote the end of a field.
53
+ * This Gem is only for importing CSV files - writing of CSV files is not supported at this time.
50
54
 
51
55
  ### Why?
52
56
 
data/Rakefile CHANGED
@@ -21,11 +21,26 @@ RuboCop::RakeTask.new
21
21
 
22
22
  require "rake/extensiontask"
23
23
 
24
- task build: :compile
24
+ if RUBY_ENGINE == 'jruby'
25
25
 
26
- Rake::ExtensionTask.new("smarter_csv") do |ext|
27
- ext.ext_dir = "ext/smarter_csv"
26
+ task default: %i[spec]
27
+
28
+ else
29
+ task build: :compile
30
+
31
+ Rake::ExtensionTask.new("smarter_csv") do |ext|
32
+ ext.lib_dir = "lib/smarter_csv"
33
+ ext.ext_dir = "ext/smarter_csv"
34
+ ext.source_pattern = "*.{c,h}"
35
+ end
36
+
37
+ # task default: %i[clobber compile spec rubocop]
38
+ task default: %i[clobber compile spec]
28
39
  end
29
40
 
30
- # task default: %i[clobber compile spec rubocop]
31
- task default: %i[clobber compile spec]
41
+ desc 'Run spec with coverage'
42
+ task :coverage do
43
+ ENV['COVERAGE'] = 'true'
44
+ Rake::Task['spec'].execute
45
+ `open coverage/index.html`
46
+ end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'mkmf'
4
-
5
4
  require "rbconfig"
5
+
6
6
  if RbConfig::MAKEFILE_CONFIG["CFLAGS"].include?("-g -O3")
7
- fixed_CFLAGS = RbConfig::MAKEFILE_CONFIG["CFLAGS"].sub("-g -O3", "$(cflags)")
7
+ fixed_CFLAGS = RbConfig::MAKEFILE_CONFIG["CFLAGS"].sub("-g -O3", "-O3 $(cflags)")
8
8
  puts("Fix CFLAGS: #{RbConfig::MAKEFILE_CONFIG["CFLAGS"]} -> #{fixed_CFLAGS}")
9
9
  RbConfig::MAKEFILE_CONFIG["CFLAGS"] = fixed_CFLAGS
10
10
  end
@@ -40,6 +40,7 @@ static VALUE rb_parse_csv_line(VALUE self, VALUE line, VALUE col_sep, VALUE quot
40
40
  long i;
41
41
 
42
42
  char prev_char = '\0'; // Store the previous character for comparison against an escape character
43
+ long backslash_count = 0; // to count consecutive backslash characters
43
44
 
44
45
  while (p < endP) {
45
46
  /* does the remaining string start with col_sep ? */
@@ -61,8 +62,13 @@ static VALUE rb_parse_csv_line(VALUE self, VALUE line, VALUE col_sep, VALUE quot
61
62
  startP = p;
62
63
  }
63
64
  } else {
64
- if (*p == *quoteP && prev_char != '\\') {
65
- quote_count += 1;
65
+ if (*p == '\\') {
66
+ backslash_count++;
67
+ } else {
68
+ if (*p == *quoteP && (backslash_count % 2 == 0)) {
69
+ quote_count++;
70
+ }
71
+ backslash_count = 0; // no more consecutive backslash characters
66
72
  }
67
73
  p++;
68
74
  }
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmarterCSV
4
+ DEFAULT_OPTIONS = {
5
+ acceleration: true,
6
+ auto_row_sep_chars: 500,
7
+ chunk_size: nil,
8
+ col_sep: :auto, # was: ',',
9
+ comment_regexp: nil, # was: /\A#/,
10
+ convert_values_to_numeric: true,
11
+ downcase_header: true,
12
+ duplicate_header_suffix: nil,
13
+ file_encoding: 'utf-8',
14
+ force_simple_split: false,
15
+ force_utf8: false,
16
+ headers_in_file: true,
17
+ invalid_byte_sequence: '',
18
+ keep_original_headers: false,
19
+ key_mapping: nil,
20
+ quote_char: '"',
21
+ remove_empty_hashes: true,
22
+ remove_empty_values: true,
23
+ remove_unmapped_keys: false,
24
+ remove_values_matching: nil,
25
+ remove_zero_values: false,
26
+ required_headers: nil,
27
+ required_keys: nil,
28
+ row_sep: :auto, # was: $/,
29
+ silence_missing_keys: false,
30
+ skip_lines: nil,
31
+ strings_as_keys: false,
32
+ strip_chars_from_headers: nil,
33
+ strip_whitespace: true,
34
+ user_provided_headers: nil,
35
+ value_converters: nil,
36
+ verbose: false,
37
+ with_line_numbers: false,
38
+ }.freeze
39
+
40
+ class << self
41
+ # NOTE: this is not called when "parse" methods are tested by themselves
42
+ def process_options(given_options = {})
43
+ puts "User provided options:\n#{pp(given_options)}\n" if given_options[:verbose]
44
+
45
+ # fix invalid input
46
+ given_options[:invalid_byte_sequence] = '' if given_options[:invalid_byte_sequence].nil?
47
+
48
+ @options = DEFAULT_OPTIONS.dup.merge!(given_options)
49
+ puts "Computed options:\n#{pp(@options)}\n" if given_options[:verbose]
50
+
51
+ validate_options!(@options)
52
+ @options
53
+ end
54
+
55
+ # NOTE: this is not called when "parse" methods are tested by themselves
56
+ #
57
+ # ONLY FOR BACKWARDS-COMPATIBILITY
58
+ def default_options
59
+ DEFAULT_OPTIONS
60
+ end
61
+
62
+ private
63
+
64
+ def validate_options!(options)
65
+ keys = options.keys
66
+ errors = []
67
+ errors << "invalid row_sep" if keys.include?(:row_sep) && !option_valid?(options[:row_sep])
68
+ errors << "invalid col_sep" if keys.include?(:col_sep) && !option_valid?(options[:col_sep])
69
+ errors << "invalid quote_char" if keys.include?(:quote_char) && !option_valid?(options[:quote_char])
70
+ raise SmarterCSV::ValidationError, errors.inspect if errors.any?
71
+ end
72
+
73
+ def option_valid?(str)
74
+ return true if str.is_a?(Symbol) && str == :auto
75
+ return true if str.is_a?(String) && !str.empty?
76
+
77
+ false
78
+ end
79
+
80
+ def pp(value)
81
+ defined?(AwesomePrint) ? value.awesome_inspect(index: nil) : value.inspect
82
+ end
83
+ end
84
+ end