csv 3.0.1 → 3.0.2

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.
@@ -2,5 +2,5 @@
2
2
 
3
3
  class CSV
4
4
  # The version of the installed library.
5
- VERSION = "3.0.1"
5
+ VERSION = "3.0.2"
6
6
  end
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "match_p"
4
+ require_relative "row"
5
+
6
+ using CSV::MatchP if CSV.const_defined?(:MatchP)
7
+
8
+ class CSV
9
+ class Writer
10
+ attr_reader :lineno
11
+ attr_reader :headers
12
+
13
+ def initialize(output, options)
14
+ @output = output
15
+ @options = options
16
+ @lineno = 0
17
+ prepare
18
+ if @options[:write_headers] and @headers
19
+ self << @headers
20
+ end
21
+ end
22
+
23
+ def <<(row)
24
+ case row
25
+ when Row
26
+ row = row.fields
27
+ when Hash
28
+ row = @headers.collect {|header| row[header]}
29
+ end
30
+
31
+ @headers ||= row if @use_headers
32
+ @lineno += 1
33
+
34
+ line = row.collect(&@quote).join(@column_separator) + @row_separator
35
+ if @output_encoding
36
+ line = line.encode(@output_encoding)
37
+ end
38
+ @output << line
39
+
40
+ self
41
+ end
42
+
43
+ def rewind
44
+ @lineno = 0
45
+ @headers = nil if @options[:headers].nil?
46
+ end
47
+
48
+ private
49
+ def prepare
50
+ @encoding = @options[:encoding]
51
+
52
+ prepare_header
53
+ prepare_format
54
+ prepare_output
55
+ end
56
+
57
+ def prepare_header
58
+ headers = @options[:headers]
59
+ case headers
60
+ when Array
61
+ @headers = headers
62
+ @use_headers = true
63
+ when String
64
+ @headers = CSV.parse_line(headers,
65
+ col_sep: @options[:column_separator],
66
+ row_sep: @options[:row_separator],
67
+ quote_char: @options[:quote_character])
68
+ @use_headers = true
69
+ when true
70
+ @headers = nil
71
+ @use_headers = true
72
+ else
73
+ @headers = nil
74
+ @use_headers = false
75
+ end
76
+ return unless @headers
77
+
78
+ converter = @options[:header_fields_converter]
79
+ @headers = converter.convert(@headers, nil, 0)
80
+ @headers.each do |header|
81
+ header.freeze if header.is_a?(String)
82
+ end
83
+ end
84
+
85
+ def prepare_format
86
+ @column_separator = @options[:column_separator].to_s.encode(@encoding)
87
+ row_separator = @options[:row_separator]
88
+ if row_separator == :auto
89
+ @row_separator = $INPUT_RECORD_SEPARATOR.encode(@encoding)
90
+ else
91
+ @row_separator = row_separator.to_s.encode(@encoding)
92
+ end
93
+ quote_character = @options[:quote_character]
94
+ quote = lambda do |field|
95
+ field = String(field)
96
+ encoded_quote_character = quote_character.encode(field.encoding)
97
+ encoded_quote_character +
98
+ field.gsub(encoded_quote_character,
99
+ encoded_quote_character * 2) +
100
+ encoded_quote_character
101
+ end
102
+ if @options[:force_quotes]
103
+ @quote = quote
104
+ else
105
+ quotable_pattern =
106
+ Regexp.new("[\r\n".encode(@encoding) +
107
+ Regexp.escape(@column_separator) +
108
+ Regexp.escape(quote_character.encode(@encoding)) +
109
+ "]".encode(@encoding))
110
+ @quote = lambda do |field|
111
+ if field.nil? # represent +nil+ fields as empty unquoted fields
112
+ ""
113
+ else
114
+ field = String(field) # Stringify fields
115
+ # represent empty fields as empty quoted fields
116
+ if field.empty? or quotable_pattern.match?(field)
117
+ quote.call(field)
118
+ else
119
+ field # unquoted field
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ def prepare_output
127
+ @output_encoding = nil
128
+ return unless @output.is_a?(StringIO)
129
+
130
+ output_encoding = @output.internal_encoding || @output.external_encoding
131
+ if @encoding != output_encoding
132
+ if @options[:force_encoding]
133
+ @output_encoding = output_encoding
134
+ else
135
+ compatible_encoding = Encoding.compatible?(@encoding, output_encoding)
136
+ if compatible_encoding
137
+ @output.set_encoding(compatible_encoding)
138
+ @output.seek(0, IO::SEEK_END)
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: csv
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 3.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Edward Gray II
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-12-07 00:00:00.000000000 Z
12
+ date: 2018-12-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -78,14 +78,18 @@ extensions: []
78
78
  extra_rdoc_files: []
79
79
  files:
80
80
  - LICENSE.txt
81
+ - NEWS.md
81
82
  - README.md
82
83
  - lib/csv.rb
83
84
  - lib/csv/core_ext/array.rb
84
85
  - lib/csv/core_ext/string.rb
86
+ - lib/csv/fields_converter.rb
87
+ - lib/csv/match_p.rb
88
+ - lib/csv/parser.rb
85
89
  - lib/csv/row.rb
86
90
  - lib/csv/table.rb
87
91
  - lib/csv/version.rb
88
- - news.md
92
+ - lib/csv/writer.rb
89
93
  homepage: https://github.com/ruby/csv
90
94
  licenses:
91
95
  - BSD-2-Clause
@@ -106,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
110
  version: '0'
107
111
  requirements: []
108
112
  rubyforge_project:
109
- rubygems_version: 3.0.0.beta3
113
+ rubygems_version: 3.0.0.beta2
110
114
  signing_key:
111
115
  specification_version: 4
112
116
  summary: CSV Reading and Writing