dbf 4.2.4 → 4.3.1
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 +9 -0
- data/LICENSE +1 -1
- data/README.md +7 -5
- data/dbf.gemspec +2 -1
- data/lib/dbf/column.rb +8 -10
- data/lib/dbf/database/foxpro.rb +1 -1
- data/lib/dbf/header.rb +2 -7
- data/lib/dbf/record.rb +2 -2
- data/lib/dbf/schema.rb +7 -7
- data/lib/dbf/table.rb +6 -7
- data/lib/dbf/version.rb +1 -1
- data/spec/dbf/column_spec.rb +2 -2
- data/spec/dbf/record_spec.rb +9 -9
- data/spec/dbf/table_spec.rb +2 -3
- data/spec/spec_helper.rb +1 -0
- metadata +19 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8d40b6c4a0c614eda7638ef810b682b3ee767153b95cc4075d90c1f12937e57c
|
4
|
+
data.tar.gz: 6b74646387585dc0d497181d2253324cf92717b217b6642f5a1e307a7413e557
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98414f9a53a66b60f69b419740cb2f28eff4bdd81de67e5b09b9ae274c1f5a2e40c8730546f4719c09078b590837b1da607685833034f96a86ab2bea62637629
|
7
|
+
data.tar.gz: 28a3a92617d4d889777d718cd88f43cec0217c6fd64135375699f81047186ddad0d1a345f32e2822d8f29a192fec579bef255efd316c5fb10594740042cd63a3
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 4.3.1
|
4
|
+
|
5
|
+
- Fix bug (since 4.2.0) that caused column names not to be truncated after null character
|
6
|
+
|
7
|
+
## 4.3.0
|
8
|
+
|
9
|
+
- Drop support for Ruby versions older than 3.0
|
10
|
+
- Require CSV gem
|
11
|
+
|
3
12
|
## 4.2.4
|
4
13
|
|
5
14
|
- Exclude unnecessary files from the gem file list
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -10,23 +10,25 @@
|
|
10
10
|
DBF is a small, fast Ruby library for reading dBase, xBase, Clipper, and FoxPro database files.
|
11
11
|
|
12
12
|
* Project page: <https://github.com/infused/dbf>
|
13
|
-
* API Documentation: <https://
|
13
|
+
* API Documentation: <https://rubydoc.info/github/infused/dbf>
|
14
14
|
* Report bugs: <https://github.com/infused/dbf/issues>
|
15
15
|
* Questions: Email <mailto:keithm@infused.org> and put DBF somewhere in the
|
16
16
|
subject line
|
17
17
|
* Change log: <https://github.com/infused/dbf/blob/master/CHANGELOG.md>
|
18
18
|
|
19
|
-
NOTE: Beginning with version 4
|
19
|
+
NOTE: Beginning with version 4.3 we have dropped support for Ruby 3.0 and earlier.
|
20
|
+
|
21
|
+
NOTE: Beginning with version 4 we have dropped support for Ruby 2.0, 2.1, 2.2, and 2.3. If you need support for these older Rubies,
|
20
22
|
please use 3.0.x (<https://github.com/infused.org/dbf/tree/3_stable>)
|
21
23
|
|
22
|
-
NOTE: Beginning with version 3
|
24
|
+
NOTE: Beginning with version 3 we have dropped support for Ruby 1.8 and 1.9. If you need support for older Rubies,
|
23
25
|
please use 2.0.x (<https://github.com/infused/dbf/tree/2_stable>)
|
24
26
|
|
25
27
|
## Compatibility
|
26
28
|
|
27
29
|
DBF is tested to work with the following versions of Ruby:
|
28
30
|
|
29
|
-
* Ruby
|
31
|
+
* Ruby 3.1.x, 3.2.x, 3.3.x
|
30
32
|
|
31
33
|
## Installation
|
32
34
|
|
@@ -362,7 +364,7 @@ Data type descriptions
|
|
362
364
|
|
363
365
|
## License
|
364
366
|
|
365
|
-
Copyright (c) 2006-
|
367
|
+
Copyright (c) 2006-2024 Keith Morrison <<keithm@infused.org>>
|
366
368
|
|
367
369
|
Permission is hereby granted, free of charge, to any person
|
368
370
|
obtaining a copy of this software and associated documentation
|
data/dbf.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.files = Dir['README.md', 'CHANGELOG.md', 'LICENSE', '{bin,lib,spec}/**/*', 'dbf.gemspec']
|
19
19
|
s.require_paths = ['lib']
|
20
20
|
s.required_rubygems_version = Gem::Requirement.new('>= 1.3.0')
|
21
|
-
s.required_ruby_version = Gem::Requirement.new('>=
|
21
|
+
s.required_ruby_version = Gem::Requirement.new('>= 3.0.0')
|
22
22
|
s.metadata['rubygems_mfa_required'] = 'true'
|
23
|
+
s.add_runtime_dependency 'csv'
|
23
24
|
end
|
data/lib/dbf/column.rb
CHANGED
@@ -9,8 +9,10 @@ module DBF
|
|
9
9
|
end
|
10
10
|
|
11
11
|
attr_reader :table, :name, :type, :length, :decimal
|
12
|
+
|
12
13
|
def_delegator :type_cast_class, :type_cast
|
13
14
|
|
15
|
+
# rubocop:disable Style/MutableConstant
|
14
16
|
TYPE_CAST_CLASS = {
|
15
17
|
N: ColumnType::Number,
|
16
18
|
I: ColumnType::SignedLong,
|
@@ -24,6 +26,7 @@ module DBF
|
|
24
26
|
G: ColumnType::General,
|
25
27
|
'+'.to_sym => ColumnType::SignedLong2
|
26
28
|
}
|
29
|
+
# rubocop:enable Style/MutableConstant
|
27
30
|
TYPE_CAST_CLASS.default = ColumnType::String
|
28
31
|
TYPE_CAST_CLASS.freeze
|
29
32
|
|
@@ -58,7 +61,7 @@ module DBF
|
|
58
61
|
#
|
59
62
|
# @return [Hash]
|
60
63
|
def to_hash
|
61
|
-
{name
|
64
|
+
{name:, type:, length:, decimal:}
|
62
65
|
end
|
63
66
|
|
64
67
|
# Underscored name
|
@@ -68,22 +71,17 @@ module DBF
|
|
68
71
|
#
|
69
72
|
# @return [String]
|
70
73
|
def underscored_name
|
71
|
-
@underscored_name ||=
|
72
|
-
|
73
|
-
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
74
|
-
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
75
|
-
.tr('-', '_')
|
76
|
-
.downcase
|
77
|
-
end
|
74
|
+
@underscored_name ||= name.gsub(/([a-z\d])([A-Z])/, '\1_\2').tr('-', '_').downcase
|
75
|
+
|
78
76
|
end
|
79
77
|
|
80
78
|
private
|
81
79
|
|
82
80
|
def clean(value) # :nodoc:
|
83
|
-
value.strip.
|
81
|
+
value.strip.partition("\x00").first.gsub(/[^\x20-\x7E]/, '')
|
84
82
|
end
|
85
83
|
|
86
|
-
def encode(value, strip_output
|
84
|
+
def encode(value, strip_output: false) # :nodoc:
|
87
85
|
return value unless value.respond_to?(:encoding)
|
88
86
|
|
89
87
|
output = @encoding ? encode_string(value) : value
|
data/lib/dbf/database/foxpro.rb
CHANGED
data/lib/dbf/header.rb
CHANGED
@@ -1,11 +1,6 @@
|
|
1
1
|
module DBF
|
2
2
|
class Header
|
3
|
-
attr_reader :version
|
4
|
-
attr_reader :record_count
|
5
|
-
attr_reader :header_length
|
6
|
-
attr_reader :record_length
|
7
|
-
attr_reader :encoding_key
|
8
|
-
attr_reader :encoding
|
3
|
+
attr_reader :version, :record_count, :header_length, :record_length, :encoding_key, :encoding
|
9
4
|
|
10
5
|
def initialize(data)
|
11
6
|
@data = data
|
@@ -13,7 +8,7 @@ module DBF
|
|
13
8
|
end
|
14
9
|
|
15
10
|
def unpack_header
|
16
|
-
@version = @data.
|
11
|
+
@version = @data.unpack1('H2')
|
17
12
|
|
18
13
|
case @version
|
19
14
|
when '02'
|
data/lib/dbf/record.rb
CHANGED
@@ -29,7 +29,7 @@ module DBF
|
|
29
29
|
key = name.to_s
|
30
30
|
if attributes.key?(key)
|
31
31
|
attributes[key]
|
32
|
-
elsif index = underscored_column_names.index(key)
|
32
|
+
elsif (index = underscored_column_names.index(key))
|
33
33
|
attributes[@columns[index].name]
|
34
34
|
end
|
35
35
|
end
|
@@ -59,7 +59,7 @@ module DBF
|
|
59
59
|
private
|
60
60
|
|
61
61
|
def column_names # :nodoc:
|
62
|
-
@column_names ||= @columns.map
|
62
|
+
@column_names ||= @columns.map(&:name)
|
63
63
|
end
|
64
64
|
|
65
65
|
def get_data(column) # :nodoc:
|
data/lib/dbf/schema.rb
CHANGED
@@ -35,9 +35,9 @@ module DBF
|
|
35
35
|
# @param format [Symbol] format Valid options are :activerecord and :json
|
36
36
|
# @param table_only [Boolean]
|
37
37
|
# @return [String]
|
38
|
-
def schema(format = :activerecord, table_only
|
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:)
|
41
41
|
rescue NameError
|
42
42
|
raise ArgumentError, ":#{format} is not a valid schema. Valid schemas are: #{FORMATS.join(', ')}."
|
43
43
|
end
|
@@ -46,7 +46,7 @@ module DBF
|
|
46
46
|
"#{format}_schema"
|
47
47
|
end
|
48
48
|
|
49
|
-
def activerecord_schema(
|
49
|
+
def activerecord_schema(*) # :nodoc:
|
50
50
|
s = "ActiveRecord::Schema.define do\n"
|
51
51
|
s << " create_table \"#{name}\" do |t|\n"
|
52
52
|
columns.each do |column|
|
@@ -56,7 +56,7 @@ module DBF
|
|
56
56
|
s
|
57
57
|
end
|
58
58
|
|
59
|
-
def sequel_schema(table_only
|
59
|
+
def sequel_schema(table_only: false) # :nodoc:
|
60
60
|
s = ''
|
61
61
|
s << "Sequel.migration do\n" unless table_only
|
62
62
|
s << " change do\n " unless table_only
|
@@ -70,7 +70,7 @@ module DBF
|
|
70
70
|
s
|
71
71
|
end
|
72
72
|
|
73
|
-
def json_schema(
|
73
|
+
def json_schema(*) # :nodoc:
|
74
74
|
columns.map(&:to_hash).to_json
|
75
75
|
end
|
76
76
|
|
@@ -92,9 +92,9 @@ module DBF
|
|
92
92
|
|
93
93
|
def schema_data_type(column, format = :activerecord) # :nodoc:
|
94
94
|
case column.type
|
95
|
-
when
|
95
|
+
when 'N', 'F', 'I'
|
96
96
|
number_data_type(column)
|
97
|
-
when
|
97
|
+
when 'Y', 'D', 'T', 'L', 'M', 'B'
|
98
98
|
OTHER_DATA_TYPES[column.type]
|
99
99
|
else
|
100
100
|
string_data_format(format, column)
|
data/lib/dbf/table.rb
CHANGED
@@ -86,7 +86,7 @@ module DBF
|
|
86
86
|
# @return [TrueClass, FalseClass]
|
87
87
|
def close
|
88
88
|
@data.close
|
89
|
-
@memo
|
89
|
+
@memo&.close
|
90
90
|
end
|
91
91
|
|
92
92
|
# @return [TrueClass, FalseClass]
|
@@ -255,7 +255,7 @@ module DBF
|
|
255
255
|
|
256
256
|
def find_all(options) # :nodoc:
|
257
257
|
select do |record|
|
258
|
-
next unless record
|
258
|
+
next unless record&.match?(options)
|
259
259
|
|
260
260
|
yield record if block_given?
|
261
261
|
record
|
@@ -263,7 +263,7 @@ module DBF
|
|
263
263
|
end
|
264
264
|
|
265
265
|
def find_first(options) # :nodoc:
|
266
|
-
detect { |record| record
|
266
|
+
detect { |record| record&.match?(options) }
|
267
267
|
end
|
268
268
|
|
269
269
|
def foxpro? # :nodoc:
|
@@ -278,13 +278,12 @@ module DBF
|
|
278
278
|
end
|
279
279
|
|
280
280
|
def memo_class # :nodoc:
|
281
|
-
@memo_class ||=
|
282
|
-
|
283
|
-
Memo::Foxpro
|
281
|
+
@memo_class ||= if foxpro?
|
282
|
+
Memo::Foxpro
|
284
283
|
else
|
285
284
|
version == '83' ? Memo::Dbase3 : Memo::Dbase4
|
286
|
-
end
|
287
285
|
end
|
286
|
+
|
288
287
|
end
|
289
288
|
|
290
289
|
def memo_search_path(io) # :nodoc:
|
data/lib/dbf/version.rb
CHANGED
data/spec/dbf/column_spec.rb
CHANGED
@@ -287,12 +287,12 @@ RSpec.describe DBF::Column do
|
|
287
287
|
describe '#name' do
|
288
288
|
it 'contains only ASCII characters' do
|
289
289
|
column = DBF::Column.new table, "--\x1F-\x68\x65\x6C\x6C\x6F \x00world-\x80--", 'N', 1, 0
|
290
|
-
expect(column.name).to eq '---hello
|
290
|
+
expect(column.name).to eq '---hello '
|
291
291
|
end
|
292
292
|
|
293
293
|
it 'is truncated at the null character' do
|
294
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
|
295
|
+
expect(column.name).to eq '---hello '
|
296
296
|
end
|
297
297
|
end
|
298
298
|
end
|
data/spec/dbf/record_spec.rb
CHANGED
@@ -3,25 +3,25 @@ require 'spec_helper'
|
|
3
3
|
RSpec.describe DBF::Record do
|
4
4
|
describe '#to_a' do
|
5
5
|
let(:table) { DBF::Table.new fixture('dbase_83.dbf') }
|
6
|
-
let(:
|
7
|
-
let(:
|
6
|
+
let(:record0) { YAML.load_file(fixture('dbase_83_record_0.yml')) }
|
7
|
+
let(:record9) { YAML.load_file(fixture('dbase_83_record_9.yml')) }
|
8
8
|
|
9
9
|
it 'returns an ordered array of attribute values' do
|
10
10
|
record = table.record(0)
|
11
|
-
expect(record.to_a).to eq
|
11
|
+
expect(record.to_a).to eq record0
|
12
12
|
|
13
13
|
record = table.record(9)
|
14
|
-
expect(record.to_a).to eq
|
14
|
+
expect(record.to_a).to eq record9
|
15
15
|
end
|
16
16
|
|
17
17
|
describe 'with missing memo file' do
|
18
18
|
describe 'when opening a path' do
|
19
19
|
let(:table) { DBF::Table.new fixture('dbase_83_missing_memo.dbf') }
|
20
|
-
let(:
|
20
|
+
let(:record0) { YAML.load_file(fixture('dbase_83_missing_memo_record_0.yml')) }
|
21
21
|
|
22
22
|
it 'returns nil values for memo fields' do
|
23
23
|
record = table.record(0)
|
24
|
-
expect(record.to_a).to eq
|
24
|
+
expect(record.to_a).to eq record0
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -29,11 +29,11 @@ RSpec.describe DBF::Record do
|
|
29
29
|
describe 'when opening StringIO' do
|
30
30
|
let(:data) { StringIO.new(File.read(fixture('dbase_83_missing_memo.dbf'))) }
|
31
31
|
let(:table) { DBF::Table.new(data) }
|
32
|
-
let(:
|
32
|
+
let(:record0) { YAML.load_file(fixture('dbase_83_missing_memo_record_0.yml')) }
|
33
33
|
|
34
34
|
it 'returns nil values for memo fields' do
|
35
35
|
record = table.record(0)
|
36
|
-
expect(record.to_a).to eq
|
36
|
+
expect(record.to_a).to eq record0
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
@@ -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:) }
|
54
54
|
|
55
55
|
before do
|
56
56
|
allow(record).to receive(:attributes).and_return(attributes)
|
data/spec/dbf/table_spec.rb
CHANGED
@@ -70,7 +70,6 @@ RSpec.describe DBF::Table do
|
|
70
70
|
|
71
71
|
describe 'when data is StringIO' do
|
72
72
|
let(:data) { StringIO.new File.read(dbf_path) }
|
73
|
-
let(:memo) { StringIO.new File.read(memo_path) }
|
74
73
|
let(:table) { DBF::Table.new data }
|
75
74
|
|
76
75
|
let(:control_schema) { File.read(fixture('dbase_83_schema_ar.txt')) }
|
@@ -200,7 +199,7 @@ RSpec.describe DBF::Table do
|
|
200
199
|
end
|
201
200
|
|
202
201
|
it 'returns matching records when used with options' do
|
203
|
-
expect(table.find(:all, 'WEIGHT' => 0.0)).to eq
|
202
|
+
expect(table.find(:all, 'WEIGHT' => 0.0)).to eq(table.select { |r| r['weight'] == 0.0 })
|
204
203
|
end
|
205
204
|
|
206
205
|
it 'ANDS multiple search terms' do
|
@@ -295,7 +294,7 @@ RSpec.describe DBF::Table do
|
|
295
294
|
it 'is an array of Columns' do
|
296
295
|
expect(columns).to be_an(Array)
|
297
296
|
expect(columns).to_not be_empty
|
298
|
-
expect(columns).to
|
297
|
+
expect(columns).to(be_all { |c| c.is_a? DBF::Column })
|
299
298
|
end
|
300
299
|
end
|
301
300
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dbf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keith Morrison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
11
|
+
date: 2024-01-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: csv
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
description: A small fast library for reading dBase, xBase, Clipper and FoxPro database
|
14
28
|
files.
|
15
29
|
email: keithm@infused.org
|
@@ -104,14 +118,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
104
118
|
requirements:
|
105
119
|
- - ">="
|
106
120
|
- !ruby/object:Gem::Version
|
107
|
-
version:
|
121
|
+
version: 3.0.0
|
108
122
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
123
|
requirements:
|
110
124
|
- - ">="
|
111
125
|
- !ruby/object:Gem::Version
|
112
126
|
version: 1.3.0
|
113
127
|
requirements: []
|
114
|
-
rubygems_version: 3.
|
128
|
+
rubygems_version: 3.5.3
|
115
129
|
signing_key:
|
116
130
|
specification_version: 4
|
117
131
|
summary: Read xBase files
|