RSpec tests: 1,247 → 1,410 (+163 tests)
-
SmarterCSV.errors— class-level error access after anyprocess,parse,each, oreach_chunkcall. Exposes the samereader.errorshash without requiring access to theReaderinstance. Errors are cleared at the start of each call and stored per-thread (safe in Puma/Sidekiq).# Previously — required Reader instance to access errors reader = SmarterCSV::Reader.new('data.csv', on_bad_row: :skip) reader.process puts reader.errors[:bad_row_count] # Now — works with the class-level API too SmarterCSV.process('data.csv', on_bad_row: :skip) puts SmarterCSV.errors[:bad_row_count]
Note:
SmarterCSV.errorsonly surfaces errors from the most recent run on the current thread. In a multi-threaded environment (Puma, Sidekiq), each thread maintains its own error state independently. If you callSmarterCSV.processtwice in the same thread, the second call's errors replace the first's. For long-running or complex pipelines where you need to aggregate errors across multiple files, use the Reader API.
⚠️ Fibers:SmarterCSV.errorsusesThread.currentfor storage, which is shared across all fibers running in the same thread. If you process CSV files concurrently in fibers (e.g. withAsync,Falcon, or manualFiberscheduling),SmarterCSV.errorsmay return stale or wrong results. UseSmarterCSV::Readerdirectly — errors are scoped to the reader instance and are always correct regardless of fiber context.
- fixed #325:
col_sepin quoted headers was handled incorrectly; Thanks to Paho Lurie-Gregg. - fixed issue with quoted numeric fields that were not converted to numeric
- Added 163 tests covering new features and corner cases
Full details · Benchmarks · Performance notes
RSpec tests: 714 → 1,247 (+533 tests)
New option quote_boundary:
-
defaults to
:standard**: quotes are now only recognized as field delimiters at field boundaries; mid-field quotes are treated as literal characters.This aligns SmarterCSV with RFC 4180 and other CSV libraries. In practice, mid-field quotes were already producing silently corrupt output in previous versions — so most users will see correct behavior improve, not regress.
-
Use
quote_boundary: :legacyonly in exceptional cases to restore previous behavior. See Parsing Strategy.
- 1.8×–8.6× faster than Ruby
CSV.read(raw tokenization only; no post-processing) - 7×–129× faster than Ruby
CSV.table(nearest equivalent output) - up to 2.4× faster for accelerated path vs 1.15.2 (15/19 benchmark files faster)
- up to 2× faster for Ruby path vs 1.15.2
- 9×–65× faster for accelerated path vs 1.14.4
Measured on 19 benchmark files, Apple M1, Ruby 3.4.7. See benchmarks.
SmarterCSV.parse(csv_string, options): can now parse a CSV string directly. See Migrating from Ruby CSV.SmarterCSV.each/Reader#each: row-by-row enumerator;Readernow includesEnumerable.SmarterCSV.each_chunk/Reader#each_chunk: chunked enumerator yielding(Array<Hash>, chunk_index).
on_bad_row:— bad row quarantine::skip,:collect,:raise, or callable. See Bad Row Quarantine.bad_row_limit: N— raisesSmarterCSV::TooManyBadRowsafter N bad rows.collect_raw_lines:(default:true) — include raw line in bad-row error records.field_size_limit: N— cap field size in bytes; prevents DoS from unclosed quotes. RaisesSmarterCSV::FieldSizeLimitExceeded.headers: { only: [...] }/headers: { except: [...] }— column selection; excluded columns skipped in C hot path. See Column Selection.nil_values_matching:— replaces deprecatedremove_values_matching:.missing_headers:(default::auto) — replaces deprecatedstrict:.verbose: :quiet/:normal/:debug— replaces deprecatedverbose: true/false.on_start:/on_chunk:/on_complete:— instrumentation hooks. See Instrumentation.
- IO/StringIO support:
SmarterCSV.generateandWriter.newnow accept anyIO-compatible object. See Write API. SmarterCSV.generatereturns a String when called without a destination argument.- Streaming mode: when
headers:ormap_headers:is provided upfront, Writer skips the temp file and streams directly. encoding:/write_nil_value:/write_empty_value:/write_bom:— new writer options.
remove_values_matching:→ usenil_values_matching:strict:→ usemissing_headers: :raise/:autoverbose: true/false→ useverbose: :debug/:normal
- Empty headers (#324, #312): empty/whitespace-only header fields now auto-generate names via
missing_header_prefix. - All library output now goes to
$stderr— nothing written to$stdout. SmarterCSV.generateraisesArgumentError(not blankRuntimeError) when called without a block.- Writer temp file no longer hardcoded to
/tmp(fixes Windows); properly cleaned up withTempfile#close!. - Writer
StringIO:finalizeno longer attempts to close a caller-ownedStringIO.
- 1.6× to 7.2× faster than CSV.read
- 6× to 113× faster than Ruby’s CSV.table
- 5.4× to 37.4× faster than SmarterCSV 1.14.4 (with C-acceleration)
- 1.4× to 9.5× faster than SmarterCSV 1.14.4 (without C-acceleration, pure Ruby path)
- Fix for quoted fields ending with backslash (issue #316, issue #252): Since v1.8.5, SmarterCSV unconditionally treated
\"as an escaped quote, which causedMalformedCSVorEOFErrorfor CSV files containing literal backslashes in quoted fields (e.g. Windows paths like"C:\Users\").
- New option
quote_escaping: Controls how quotes are escaped inside quoted fields. Default::auto. See Parsing Strategy for details.:auto(default): Tries backslash-escape interpretation first, falls back to RFC 4180 if parsing fails. This handles both conventions automatically without breaking existing data.:double_quotes(RFC 4180): Only doubled quotes ("") escape a quote character. Backslash is always literal.:backslash(MySQL/Unix):\"is treated as an escaped quote.
-
Dropping support for Ruby 2.5
-
Performance Optimizations
- 39% less memory allocated
- 43% fewer objects created
- ~5× faster at P90 vs SmarterCSV 1.14.4
- ~3–7× faster at P90 vs Ruby CSV
-
Chunk index in block processing: When using block-based processing, an optional second parameter
chunk_indexis now passed to the block. This 0-based index is useful for progress tracking and debugging. The change is backwards compatible - existing code continues to work.SmarterCSV.process(file, chunk_size: 100) do |chunk, chunk_index| puts "Processing chunk #{chunk_index}..." Model.import(chunk) end
-
MissingKeys#keys- programmatic access to missing keys without parsing error messages (PR #314, thanks to Skye Shaw) -
DuplicateHeaders#headers- programmatic access to duplicate headers without parsing error messages# Example: accessing missing keys programmatically rescue SmarterCSV::MissingKeys => e e.keys # => [:employee_id, :department] end # Example: accessing duplicate headers programmatically rescue SmarterCSV::DuplicateHeaders => e e.headers # => [:email] end
-
New
parse_line_to_hash_cfunction: Builds Ruby hash directly during parsing, eliminating intermediate array allocations. Previously, parsing created a values array, thenzip()created pairs array, thento_h()built the hash. Now done in a single pass. -
Shared empty string optimization: Reuses a single frozen empty string for all empty CSV fields, reducing object allocations and GC pressure.
-
Faster quote counting: New
count_quote_chars_cfunction replaces Ruby'seach_chariteration, eliminating one String object allocation per character. -
Conditional nil padding: Missing columns only padded with
nilwhenremove_empty_values: false, avoiding unnecessary work in the default case.
-
Frozen regex constants: Numeric conversion patterns (
FLOAT_REGEX,INTEGER_REGEX,ZERO_REGEX) are now pre-compiled and frozen, eliminating millions of regex compilations for large files. This alone reduced numeric conversion overhead from +75% to +4%. -
In-place hash modification: Hash transformations now modify hashes in-place instead of creating copies, reducing memory allocations by 39% and object count by 43%.
Benchmarks using Ruby 3.4.7 on M1 Apple Silicon. All times in seconds.
Summary:
| Comparison | Range | Comments | P90 |
|---|---|---|---|
| vs SmarterCSV 1.14.4 | 2.6x - 3.5x faster | up to 20.5x for some | ~5x |
| vs CSV hashes | 1.9x - 3.8x faster | up to 6.7x for some | ~3x |
| vs CSV.table | 4.3x - 10.1x faster | up to 12.0x for some | ~7..8x |
P90 measured over the full set of benchmarked files
These gains come while returning fully usable hashes with conversions, not raw arrays that require post-processing.
Memory improvements: 39% less memory allocated, 43% fewer objects created
vs SmarterCSV 1.14.4:
| File | Size | Rows | 1.14.4 | 1.15.0 | Speedup |
|---|---|---|---|---|---|
| worldcities.csv | 5 MB | 48K | 1.27s | 0.49s | 2.6x |
| LANDSAT_ETM_C2_L1_50k.csv | 31 MB | 50K | 6.73s | 1.99s | 3.4x |
| PEOPLE_IMPORT.csv | 62 MB | 50K | 8.43s | 2.43s | 3.5x |
| wide_500_cols_20k.csv | 98 MB | 20K | 19.38s | 5.09s | 3.8x |
| long_fields_20k.csv | 22 MB | 20K | 3.05s | 0.15s | 20.5x |
| embedded_newlines_20k.csv | 1.5 MB | 20K | 0.59s | 0.12s | 5.1x |
vs Ruby CSV 3.3.5:
For an apples-to-apples comparison, we must compare parsers that return the same result structure and perform comparable work. SmarterCSV returns an array of hashes with symbol keys and type conversion applied, so raw CSV array parsing is not a fair comparison.
Beware of comparisons that focus solely on raw CSV parsing. Such benchmarks measure only tokenization, while real-world usage still requires substantial post-processing to produce usable data. Leaving this work out -- hash construction, normalization, type conversion, and edge-case handling to produce usable data -- consistently understates the actual cost of CSV ingestion.
For this reason, CSV.table is the closest equivalent to SmarterCSV.
| File | Size | Rows | CSV hashes | CSV.table | 1.15.0 | vs hashes | vs table |
|---|---|---|---|---|---|---|---|
| worldcities.csv | 5 MB | 48K | 1.06s | 2.12s | 0.49s | 2.2x | 4.3x |
| LANDSAT_ETM_C2_L1_50k.csv | 31 MB | 50K | 3.85s | 9.25s | 1.99s | 1.9x | 4.7x |
| PEOPLE_IMPORT.csv | 62 MB | 50K | 9.10s | 24.39s | 2.43s | 3.8x | 10.1x |
| wide_500_cols_20k.csv | 98 MB | 20K | 34.24s | 61.24s | 5.09s | 6.7x | 12.0x |
| long_fields_20k.csv | 22 MB | 20K | 0.34s | 0.81s | 0.15s | 2.3x | 5.5x |
| whitespace_heavy_20k.csv | 3.3 MB | 20K | 0.30s | 0.83s | 0.12s | 2.5x | 7.0x |
CSV hashes = CSV.read(file, headers: true).map(&:to_h) (string keys, no conversion, still requires post-processing)
CSV.table = CSV.table(file).map(&:to_h) (symbol keys + numeric conversion, still requires post-processing)
worldcities.csv is from here
- Fix compilation error on ARM macOS (
-march=nativeunsupported) (PR #313, thanks to Skye Shaw) - CI improvements: Ruby 3.4 support, Codecov action update (PR #311, thanks to Mark Bumiller)
- Bugfix: SmarterCSV::Reader fixing issue with header containing spaces (PR 305 thanks to Felipe Cabezudo)
- Improved C-extension parsing logic:
- Added fast path for unquoted fields to avoid unnecessary quote checks.
- Aded inline whitespace stripping inside the C parser
- Performance
- Significantly reduced per-line overhead in non-quoted, wide CSVs (e.g. fixed-width data exports).
- Benchmarks show ~10–40% speedup over v1.14.2 depending on structure and quoting.
- bugfix: SmarterCSV::Writer fixing corner case with
quote_headers: true(issue 301) - new option:
header_converterallows to programatically modify the headers
- bugfix: SmarterCSV::Writer empty hash results in a blank line (issue 299)
- bugfix: SmarterCSV::Writer need to automatically quote problematic headers (issue #300)
- new option:
quote_headersallows to explicitly quote all headers
- adding advanced configuration options for writing CSV files. (issue 297 thanks to Robert Reiz, issue 296)
- fix bug with SmarterCSV.generate with
force_quotes: true(issue 294)
The changes are to improve robustness and to reduce the risk of data loss
-
implementing auto-detection of extra columns (thanks to James Fenley)
-
improved handling of unbalanced quote_char in input (issue 288) thanks to Simon Rentzke), and (issue 283) thanks to James Fenley, Randall B, Matthew Kennedy) -> SmarterCSV will now raise
SmarterCSV::MalformedCSVfor unbalanced quote_char. -
bugfix / improved handling of extra columns in input data (issue 284) (thanks to James Fenley)
-
previous behavior: when a CSV row had more columns than listed in the header, the additional columns were ignored
-
new behavior:
- new default behavior is to auto-generate additional headers, e.g. :column_7, :column_8, etc
- you can set option
:strictto true in order to get aSmarterCSV::MalformedCSVexception instead
-
-
setting
user_provided_headersnow impliesheaders_in_file: false(issue 282)The option
user_provided_headerscan be used to specify headers when there are none in the input, OR to completely override headers that are in the input (file).SmarterCSV is now using a safer default behavior.
-
previous behavior: Setting
user_provided_headersdid not change the defaultheaders_in_file: trueIf the input had no headers, this would cause the first line to be erroneously treated as a header, and the user could lose the first row of data. -
new behavior: Setting
user_provided_headerssetsheaders_in_file: falsea) Improved behavior if there was no header in the input data. b) If there was a header in the input data, anduser_provided_headersis used to override the headers in the file, then please explicitly specifyheaders_in_file: true, otherwise you will get an extra hash which includes the header data.
IF you set
user_provided_headersand the file has a header, then provideheaders_in_file: trueto avoid getting that extra record. -
-
improved documentation for handling of numeric columns with leading zeroes, e.g. ZIP codes. (issue #151 thanks to David Moles).
convert_values_to_numeric: { except: [:zip] }will return a string for that column instead (since version 1.10.x)
- Improved column separator detection by ignoring quoted sections #276 (thanks to Nicolas Castellanos)
-
Added Thread-Safety: added SmarterCSV::Reader to process CSV files in a thread-safe manner (issue #277)
-
SmarterCSV::Writer changed default row separator to the system's row separator (
\non Linux,\r\non Windows) -
added a doc tree
-
POTENTIAL ISSUE:
Version 1.12.x has a change of the underlying implementation of
SmarterCSV.process(file_or_input, options, &block). Underneath it now uses this interface:reader = SmarterCSV::Reader.new(file_or_input, options) # either simple one-liner: data = reader.process # or block format: data = reader.process do # do something here endIt still supports calling
SmarterCSV.processfor backwards-compatibility, but it no longer provides access to the internal state, e.g. raw_headers.SmarterCSV.raw_headers->reader.raw_headersSmarterCSV.headers->reader.headersIf you need these features, please update your code to create an instance of
SmarterCSV::Readeras shown above.
- fixing missing errors definition
- improved behavior of Writer class
- added SmarterCSV.generate shortcut for CSV writing
- added SmarterCSV::Writer to output CSV files (issue #44)
- fixed issue when frozen options are handed in (thanks to Daniel Pepper)
- cleaned-up rspec tests (thanks to Daniel Pepper)
- fixed link in README (issue #251)
- improve error message for missing keys
- fix incorrect warning about UTF-8 (issue #268, thanks hirowatari)
-
BREAKING CHANGES:
Changed behavior:
-
when
user_provided_headersare provided:- if they are not unique, an exception will now be raised
- they are taken "as is", no header transformations can be applied
- when they are given as strings or as symbols, it is assumed that this is the desired format
- the value of the
strings_as_keysoptions will be ignored
-
option
duplicate_header_suffixnow defaults to''instead ofnil.- this allows automatic disambiguation when processing of CSV files with duplicate headers, by appending a number
- explicitly set this option to
nilto get the behavior from previous versions.
-
-
performance and memory improvements
-
code refactor
- raise SmarterCSV::IncorrectOption when
user_provided_headersare empty - code refactor / no functional changes
- added test cases
- fixed bug with '\' at end of line (issue #252, thanks to averycrespi-moz)
- fixed require statements (issue #249, thanks to PikachuEXE, courtsimas)
- yanked
- no functional changes
- refactored directory structure
- re-added JRuby and TruffleRuby to CI tests
- no C-accelleration for JRuby
- refactored options parsing
- code coverage / rubocop
-
fixed issue #139
-
Error
SmarterCSV::MissingHeaderswas renamed toSmarterCSV::MissingKeys -
CHANGED BEHAVIOR: When
key_mappingoption is used. (issue #139) Previous versions just printed an error message when a CSV header was missing during key mapping. Versions >= 1.9 will throwSmarterCSV::MissingHeaderslisting all headers that were missing during mapping. -
Notable details for
key_mappingandrequired_headers:key_mappingis applied to the headers early on duringSmarterCSV.process, and raises an error if a header in the input CSV file is missing, and we can not map that header to its desired name.
Mapping errors can be surpressed by using:
-
silence_missing_keysset totrue, which silence all such errors, making all headers for mapping optional. -
silence_missing_keysgiven an Array with the specific header keys that are optional The use case is that some header fields are optional, but we still want them renamed if they are present. -
required_headerschecks which headers are present afterkey_mappingwas applied.
- fix parsing of escaped quote characters (thanks to JP Camara)
- fix gem loading issue (issue #232, #234)
- bugfix: windows one-column files were raising NoColSepDetected (issue #229)
- bugfix: do not raise
NoColSepDetectedfor CSV files with only one column in most cases (issue #222) If the first lines contain non-ASCII characters, and no col_sep is detected, it will still raiseNoColSepDetected
- added validation against invalid values for :col_sep, :row_sep, :quote_char (issue #216)
- deprecating
required_headersand replace withrequired_keys(issue #140) - fixed issue with require statement
-
NEW DEFAULTS:
col_sep: :auto,row_sep: :auto. Fully automatic detection by default.MAKE SURE to rescue
NoColSepDetectedif your CSV files can have unexpected formats, e.g. from users uploading them to a service, and handle those cases. -
ignore Byte Order Marker (BOM) in first line in file (issues #27, #219)
- improved guessing of the column separator, thanks to Alessandro Fazzi
- new option :silence_missing_keys; if set to true, it ignores missing keys in
key_mapping
- new option :with_line_numbers; if set to true, it adds :csv_line_number to each data hash (issue #130)
- bugfix for issue #195 #197 #200 which only appeared when called from Rails (thanks to Viacheslav Markin, Nicolas Rodriguez)
- added native code to accellerate line parsing by >10x over 1.6.0
- added option
acceleration, defaulting totrue, to enable native code. Disable this option to use the ruby code for line parsing. - increased test coverage to 100%
- rubocop changes
- fixed compiling
- rubocop changes
- published pre-release
- added native code to accellerate line parsing by >10x over 1.6.0
- added option
acceleration, defaulting totrue, to enable native code. Disable this option to use the ruby code for line parsing. - increased test coverage to 100%
- unused keys in
key_mappingnow generate a warning, no longer raise an exception This is preferable whenkey_mappingis done defensively for variabilities in the CSV files.
- completely rewrote line parser
- added methods
SmarterCSV.raw_headersandSmarterCSV.headersto allow easy examination of how the headers are processed.
- added missing keys to the SmarterCSV::KeyMappingError exception message #189 (thanks to John Dell)
- added raising of
KeyMappingErrorifkey_mappingrefers to a non-existent key - added option
duplicate_header_suffix(thanks to Skye Shaw) When given a non-nil string, it uses the suffix to append numbering 2..n to duplicate headers. If your code will need to process arbitrary CSV files, please setduplicate_header_suffix.
-
fixed bug with trailing col_sep characters, introduced in 1.4.0
-
Fix deprecation warning in Ruby 3.0.3 / $INPUT_RECORD_SEPARATOR (thanks to Joel Fouse )
-
changed default for
comment_regexpto benilfor a safer default behavior (thanks to David Lazar) Note This no longer assumes that lines starting with#are comments. If you want to treat lines starting with '#' as comments, usecomment_regexp: /\A#/
- fixed issue with simplecov
- minor fix: also support
col_sep: :auto - added simplecov
- dropped GPL license, smarter_csv is now only using the MIT License
- added experimental option
col_sep: 'autoto auto-detect the column separator (issue #183) The default behavior is still to assume,is the column separator. - fixed buggy behavior when using
remove_empty_values: false(issue #168) - fixed Ruby 3.0 deprecation
-
fix bug for key_mappings (issue #181)
The values of thekey_mappingshash will now be used "as is", and no longer forced to be symbolsUsers with existing code with
--key_mappingsneed to change their code to- either use symbols in the
key_mappinghash - or change the expected keys from symbols to strings
- either use symbols in the
- fix bug for key_mappings (issue #181)
The values of the
key_mappingshash will now be used "as is", and no longer forced to be symbols
- fix deprecation warnings on Ruby 2.7 (thank to Diego Salido)
- fixing error caused by calling f.close when we do not hand in a file
- fixing issue #136 with comments in CSV files
- fixing error class hierarchy
- using Rails blank? if it's available
- fixed regression / test
- fuxed quote_char interpolation for headers, but not data (thanks to Colin Petruno)
- bugfix (thanks to Joshua Smith for reporting)
- add default validation that a header can only appear once
- add option
required_headers
- fix issue with invalid byte sequences in header (issue #103, thanks to Dave Myron)
- fix issue with invalid byte sequences in multi-line data (thanks to Ivan Ushakov)
- analyze only 500 characters by default when
:row_sep => :autois used. added optionrow_sep_auto_charsto change the default if necessary. (thanks to Matthieu Paret)
- fixing UTF-8 related bug which was introduced in 1.1.2 (thanks to Tirdad C.)
- added warning when options indicate UTF-8 processing, but input filehandle is not opened with r:UTF-8 option
- added option
invalid_byte_sequence(thanks to polycarpou) - added comments on handling of UTF-8 encoding when opening from File vs. OpenURI (thanks to KevinColemanInc)
- added option to
skip_lines(thanks to wal) - added option to
force_utf8encoding (thanks to jordangraft) - bugfix if no headers in input data (thanks to esBeee)
- ensure input file is closed (thanks to waldyr)
- improved verbose output (thankd to benmaher)
- improved documentation
- added feature :value_converters, which allows parsing of dates, money, and other things (thanks to Raphaël Bleuse, Lucas Camargo de Almeida, Alejandro)
- added error if :headers_in_file is set to false, and no :user_provided_headers are given (thanks to innhyu)
- added support to convert dashes to underscore characters in headers (thanks to César Camacho)
- fixing automatic detection of \r\n line-endings (thanks to feens)
- added option :keep_original_headers to keep CSV-headers as-is (thanks to Benjamin Thouret)
- added support for multi-line fields / csv fields containing CR (thanks to Chris Hilton) (issue #31)
- added option to set :row_sep to :auto , for automatic detection of the row-separator (issue #22)
- :convert_values_to_numeric option can now be qualified with :except or :only (thanks to Hugo Lepetit)
- removed deprecated
process_csvmethod
- new option:
- :remove_unmapped_keys to completely ignore columns which were not mapped with :key_mapping (thanks to Dave Sanders)
- added GPL-2 and MIT license to GEM spec file; if you need another license contact me
- added RSpec tests
- bugfix : fixed issue #18 - fixing issue with last chunk not being properly returned (thanks to Jordan Running)
- added RSpec tests
- bugfix : fixed issue #14 - passing options along to CSV.parse (thanks to Marcos Zimmermann)
- bugfix : fixed issue #13 with negative integers and floats not being correctly converted (thanks to Graham Wetzler)
- bugfix : fixed issue with nil values in inputs with quote-char (thanks to Félix Bellanger)
- new options:
- :force_simple_split : to force simiple splitting on :col_sep character for non-standard CSV-files. e.g. without properly escaped :quote_char
- :verbose : print out line number while processing (to track down problems in input files)
- allowing process to work with objects with a 'readline' method (thanks to taq)
- added options:
- :file_encoding : defaults to utf8 (thanks to MrTin, Paxa)
- bugfix : quoted fields are now correctly parsed
- bugfix : for :headers_in_file option
- renamed the following options:
- :strip_whitepace_from_values => :strip_whitespace - removes leading/trailing whitespace from headers and values
- added the following options:
- :strip_whitepace_from_values - removes leading/trailing whitespace from values
- added more options for dealing with headers:
- :user_provided_headers ,user provided Array with header strings or symbols, to precisely define what the headers should be, overriding any in-file headers (default: nil)
- :headers_in_file , if the file contains headers as the first line (default: true)
-
added the following options:
- :downcase_header
- :strings_as_keys
- :remove_zero_values
- :remove_values_matching
- :remove_empty_hashes
- :convert_values_to_numeric
-
renamed the following options:
- :remove_empty_fields => :remove_empty_values
- renamed
SmarterCSV.process_csvtoSmarterCSV.process.