dbf 4.3.1 → 5.0.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/bin/dbf +1 -0
- data/lib/dbf/column.rb +6 -24
- data/lib/dbf/column_type.rb +3 -3
- data/lib/dbf/database/foxpro.rb +1 -1
- data/lib/dbf/schema.rb +1 -1
- data/lib/dbf/table.rb +16 -1
- data/lib/dbf/version.rb +1 -1
- data/spec/dbf/column_spec.rb +1 -13
- data/spec/dbf/encoding_spec.rb +47 -0
- data/spec/dbf/record_spec.rb +1 -1
- data/spec/fixtures/cp1251_summary.txt +1 -0
- data/spec/fixtures/dbase_03_cyrillic.dbf +0 -0
- data/spec/fixtures/dbase_03_cyrillic_summary.txt +11 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a59c64cae2987160691a8cc8e99ed63e68cd7e50b5dbc1941a186454d5c37903
|
4
|
+
data.tar.gz: 618e8a2512bab2d9cedf26e94e1bca45159db880d11243695669c3bbc43452ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cdd9d908bbc01b061d300ce780c83577f0bbaff1dcaba5375a69e71d43714d599a62879c0f6f56537a7d059764fc32102ca97eb67c4cafe6c38a68563ec88f74
|
7
|
+
data.tar.gz: 663fc952afb30bf77a5287edac7118ce5ab649cf3819f4a40994dd2f533765be9c42ec5e825a3443b47f5eba79393216fdc1448a6ebfd95fd8e1016d2fc69283
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 5.0.0
|
4
|
+
|
5
|
+
- Refactor the Column class to support non-ASCII header names
|
6
|
+
- Output encoding is now set to UTF-8 if there is no embedded encoding and one is not
|
7
|
+
specified during DBF::Table initialization.
|
8
|
+
|
9
|
+
## 4.3.2
|
10
|
+
|
11
|
+
- Fixes to maintain support for Ruby 3.0.x until it's EOL
|
12
|
+
|
3
13
|
## 4.3.1
|
4
14
|
|
5
15
|
- Fix bug (since 4.2.0) that caused column names not to be truncated after null character
|
data/bin/dbf
CHANGED
@@ -41,6 +41,7 @@ else
|
|
41
41
|
puts
|
42
42
|
puts "Database: #{filename}"
|
43
43
|
puts "Type: (#{table.version}) #{table.version_description}"
|
44
|
+
puts "Encoding: #{table.header_encoding}" if table.header_encoding
|
44
45
|
puts "Memo File: #{table.has_memo_file? ? 'true' : 'false'}"
|
45
46
|
puts "Records: #{table.record_count}"
|
46
47
|
|
data/lib/dbf/column.rb
CHANGED
@@ -8,7 +8,7 @@ module DBF
|
|
8
8
|
class NameError < StandardError
|
9
9
|
end
|
10
10
|
|
11
|
-
attr_reader :table, :name, :type, :length, :decimal
|
11
|
+
attr_reader :table, :name, :type, :length, :decimal, :encoding
|
12
12
|
|
13
13
|
def_delegator :type_cast_class, :type_cast
|
14
14
|
|
@@ -38,13 +38,14 @@ module DBF
|
|
38
38
|
# @param length [Integer]
|
39
39
|
# @param decimal [Integer]
|
40
40
|
def initialize(table, name, type, length, decimal)
|
41
|
+
@encoding = table.encoding
|
42
|
+
|
41
43
|
@table = table
|
42
44
|
@name = clean(name)
|
43
45
|
@type = type
|
44
46
|
@length = length
|
45
47
|
@decimal = decimal
|
46
48
|
@version = table.version
|
47
|
-
@encoding = table.encoding
|
48
49
|
|
49
50
|
validate_length
|
50
51
|
validate_name
|
@@ -61,7 +62,7 @@ module DBF
|
|
61
62
|
#
|
62
63
|
# @return [Hash]
|
63
64
|
def to_hash
|
64
|
-
{name
|
65
|
+
{name: name, type: type, length: length, decimal: decimal}
|
65
66
|
end
|
66
67
|
|
67
68
|
# Underscored name
|
@@ -72,37 +73,18 @@ module DBF
|
|
72
73
|
# @return [String]
|
73
74
|
def underscored_name
|
74
75
|
@underscored_name ||= name.gsub(/([a-z\d])([A-Z])/, '\1_\2').tr('-', '_').downcase
|
75
|
-
|
76
76
|
end
|
77
77
|
|
78
78
|
private
|
79
79
|
|
80
80
|
def clean(value) # :nodoc:
|
81
|
-
value.strip.partition("\x00").first
|
82
|
-
end
|
83
|
-
|
84
|
-
def encode(value, strip_output: false) # :nodoc:
|
85
|
-
return value unless value.respond_to?(:encoding)
|
86
|
-
|
87
|
-
output = @encoding ? encode_string(value) : value
|
88
|
-
strip_output ? output.strip : output
|
89
|
-
end
|
90
|
-
|
91
|
-
def encoding_args # :nodoc:
|
92
|
-
@encoding_args ||= [
|
93
|
-
Encoding.default_external,
|
94
|
-
{undef: :replace, invalid: :replace}
|
95
|
-
]
|
96
|
-
end
|
97
|
-
|
98
|
-
def encode_string(string) # :nodoc:
|
99
|
-
string.force_encoding(@encoding).encode(*encoding_args)
|
81
|
+
table.encode_string(value.strip.partition("\x00").first)
|
100
82
|
end
|
101
83
|
|
102
84
|
def type_cast_class # :nodoc:
|
103
85
|
@type_cast_class ||= begin
|
104
86
|
klass = @length == 0 ? ColumnType::Nil : TYPE_CAST_CLASS[type.to_sym]
|
105
|
-
klass.new(
|
87
|
+
klass.new(self)
|
106
88
|
end
|
107
89
|
end
|
108
90
|
|
data/lib/dbf/column_type.rb
CHANGED
@@ -5,9 +5,9 @@ module DBF
|
|
5
5
|
|
6
6
|
# @param decimal [Integer]
|
7
7
|
# @param encoding [String, Encoding]
|
8
|
-
def initialize(
|
9
|
-
@decimal = decimal
|
10
|
-
@encoding = encoding
|
8
|
+
def initialize(column)
|
9
|
+
@decimal = column.decimal
|
10
|
+
@encoding = column.encoding
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
data/lib/dbf/database/foxpro.rb
CHANGED
data/lib/dbf/schema.rb
CHANGED
@@ -37,7 +37,7 @@ module DBF
|
|
37
37
|
# @return [String]
|
38
38
|
def schema(format = :activerecord, table_only: false)
|
39
39
|
schema_method_name = schema_name(format)
|
40
|
-
send(schema_method_name, table_only:)
|
40
|
+
send(schema_method_name, table_only: table_only)
|
41
41
|
rescue NameError
|
42
42
|
raise ArgumentError, ":#{format} is not a valid schema. Valid schemas are: #{FORMATS.join(', ')}."
|
43
43
|
end
|
data/lib/dbf/table.rb
CHANGED
@@ -76,7 +76,7 @@ module DBF
|
|
76
76
|
# @param encoding [optional String, Encoding] encoding Name of the encoding or an Encoding object
|
77
77
|
def initialize(data, memo = nil, encoding = nil)
|
78
78
|
@data = open_data(data)
|
79
|
-
@encoding = encoding || header.encoding
|
79
|
+
@encoding = encoding || header.encoding || Encoding.default_external
|
80
80
|
@memo = open_memo(data, memo)
|
81
81
|
yield self if block_given?
|
82
82
|
end
|
@@ -211,6 +211,21 @@ module DBF
|
|
211
211
|
VERSIONS[version]
|
212
212
|
end
|
213
213
|
|
214
|
+
# Encode string
|
215
|
+
#
|
216
|
+
# @param [String] string
|
217
|
+
# @return [String]
|
218
|
+
def encode_string(string) # :nodoc:
|
219
|
+
string.force_encoding(@encoding).encode(Encoding.default_external, undef: :replace, invalid: :replace)
|
220
|
+
end
|
221
|
+
|
222
|
+
# Encoding specified in the file header
|
223
|
+
#
|
224
|
+
# @return [Encoding]
|
225
|
+
def header_encoding
|
226
|
+
header.encoding
|
227
|
+
end
|
228
|
+
|
214
229
|
private
|
215
230
|
|
216
231
|
def build_columns # :nodoc:
|
data/lib/dbf/version.rb
CHANGED
data/spec/dbf/column_spec.rb
CHANGED
@@ -37,7 +37,7 @@ RSpec.describe DBF::Column do
|
|
37
37
|
|
38
38
|
describe 'with empty column name' do
|
39
39
|
it 'raises DBF::Column::NameError' do
|
40
|
-
expect { DBF::Column.new table,
|
40
|
+
expect { DBF::Column.new table, '', 'N', 1, 0 }.to raise_error(DBF::Column::NameError)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -283,16 +283,4 @@ RSpec.describe DBF::Column do
|
|
283
283
|
end
|
284
284
|
end
|
285
285
|
end
|
286
|
-
|
287
|
-
describe '#name' do
|
288
|
-
it 'contains only ASCII characters' do
|
289
|
-
column = DBF::Column.new table, "--\x1F-\x68\x65\x6C\x6C\x6F \x00world-\x80--", 'N', 1, 0
|
290
|
-
expect(column.name).to eq '---hello '
|
291
|
-
end
|
292
|
-
|
293
|
-
it 'is truncated at the null character' do
|
294
|
-
column = DBF::Column.new table, "--\x1F-\x68\x65\x6C\x6C\x6F \x00world-\x80\x80--", 'N', 1, 0
|
295
|
-
expect(column.name).to eq '---hello '
|
296
|
-
end
|
297
|
-
end
|
298
286
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe 'default encoding' do
|
6
|
+
let(:dbf_path) { fixture('dbase_03_cyrillic.dbf') }
|
7
|
+
let(:table) { DBF::Table.new dbf_path }
|
8
|
+
|
9
|
+
it 'defaults to UTF-8 encoding' do
|
10
|
+
expect(table.encoding).to eq Encoding::UTF_8
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'uses the table encoding for column encoding' do
|
14
|
+
column = table.columns.first
|
15
|
+
expect(column.encoding).to eq table.encoding
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'encodes column names' do
|
19
|
+
expect(table.column_names).to eq ['ШАР', 'ПЛОЩА']
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'encodes record values' do
|
23
|
+
expect(table.record(0).attributes['ШАР']).to eq 'Номер'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
RSpec.describe 'embedded encoding' do
|
28
|
+
let(:dbf_path) { fixture('cp1251.dbf') }
|
29
|
+
let(:table) { DBF::Table.new dbf_path }
|
30
|
+
|
31
|
+
it 'defaults to UTF-8 encoding' do
|
32
|
+
expect(table.encoding).to eq 'cp1251'
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'uses the table encoding for column encoding' do
|
36
|
+
column = table.columns.first
|
37
|
+
expect(column.encoding).to eq table.encoding
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'encodes column names' do
|
41
|
+
expect(table.column_names).to eq ['RN', 'NAME']
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'encodes record values' do
|
45
|
+
expect(table.record(0).attributes['NAME']).to eq 'амбулаторно-поликлиническое'
|
46
|
+
end
|
47
|
+
end
|
data/spec/dbf/record_spec.rb
CHANGED
@@ -50,7 +50,7 @@ RSpec.describe DBF::Record do
|
|
50
50
|
|
51
51
|
describe 'if other attributes match' do
|
52
52
|
let(:attributes) { {x: 1, y: 2} }
|
53
|
-
let(:other) { instance_double('DBF::Record', attributes:) }
|
53
|
+
let(:other) { instance_double('DBF::Record', attributes: attributes) }
|
54
54
|
|
55
55
|
before do
|
56
56
|
allow(record).to receive(:attributes).and_return(attributes)
|
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dbf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 5.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keith Morrison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: csv
|
@@ -56,6 +56,7 @@ files:
|
|
56
56
|
- lib/dbf/version.rb
|
57
57
|
- spec/dbf/column_spec.rb
|
58
58
|
- spec/dbf/database/foxpro_spec.rb
|
59
|
+
- spec/dbf/encoding_spec.rb
|
59
60
|
- spec/dbf/file_formats_spec.rb
|
60
61
|
- spec/dbf/record_spec.rb
|
61
62
|
- spec/dbf/table_spec.rb
|
@@ -64,6 +65,8 @@ files:
|
|
64
65
|
- spec/fixtures/dbase_02.dbf
|
65
66
|
- spec/fixtures/dbase_02_summary.txt
|
66
67
|
- spec/fixtures/dbase_03.dbf
|
68
|
+
- spec/fixtures/dbase_03_cyrillic.dbf
|
69
|
+
- spec/fixtures/dbase_03_cyrillic_summary.txt
|
67
70
|
- spec/fixtures/dbase_03_summary.txt
|
68
71
|
- spec/fixtures/dbase_30.dbf
|
69
72
|
- spec/fixtures/dbase_30.fpt
|
@@ -125,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
128
|
- !ruby/object:Gem::Version
|
126
129
|
version: 1.3.0
|
127
130
|
requirements: []
|
128
|
-
rubygems_version: 3.5.
|
131
|
+
rubygems_version: 3.5.8
|
129
132
|
signing_key:
|
130
133
|
specification_version: 4
|
131
134
|
summary: Read xBase files
|