ndr_import 11.6.0 → 11.8.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 +17 -0
- data/README.md +1 -1
- data/lib/ndr_import/csv_cell.rb +13 -0
- data/lib/ndr_import/file/all.rb +1 -0
- data/lib/ndr_import/file/base.rb +1 -1
- data/lib/ndr_import/file/delimited.rb +1 -1
- data/lib/ndr_import/file/gzip.rb +66 -0
- data/lib/ndr_import/file/zip.rb +8 -1
- data/lib/ndr_import/helpers/file/delimited.rb +2 -2
- data/lib/ndr_import/table.rb +45 -6
- data/lib/ndr_import/universal_importer_helper.rb +22 -1
- data/lib/ndr_import/vcf/table.rb +5 -1
- data/lib/ndr_import/version.rb +1 -1
- data/lib/ndr_import.rb +1 -1
- metadata +37 -27
- data/lib/ndr_import/csv_library.rb +0 -74
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c16e2b4fa7494365c5c55d5b8947641a3396cd58bf53ae6914525554cdf565a1
|
|
4
|
+
data.tar.gz: ca00a216b0bf6542e03777c60b26a41b2824c3902da8b3bee2bd12369b3e0197
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b0fa0f74a4c2a1cf3d036a26aa60e186b56531fb3d4328c68ead64b6d8fc81a046f7eca633f5e9acd149121debae3ecf67f83d52f7a56ad316da46f1b963a9ff
|
|
7
|
+
data.tar.gz: e9f9a6adb560d9d5fce254e9a33a869dfeb57e4121b2ecb8a6b4d501b9b4bc965021805e912eb7dad37f899bf3eeb0340367f1232a595580cfcef6bef1960a32
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
* no unreleased changes
|
|
3
3
|
|
|
4
|
+
## 11.8.0 / 2026-11-03
|
|
5
|
+
### Added
|
|
6
|
+
* Support Gzip/gz
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
* Removed deprecated `CSVLibrary`
|
|
10
|
+
* Minimum `rubyzip` version is now 2.4
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
* Drop support for Rails 7.1, 7.2
|
|
14
|
+
* Fix bug in VCF metadata
|
|
15
|
+
* Fix bug where table columns are mutated by a regexp column
|
|
16
|
+
|
|
17
|
+
## 11.7.0 / 2026-09-24
|
|
18
|
+
### Added
|
|
19
|
+
* Added the ability to define a virtual :filename column
|
|
20
|
+
|
|
4
21
|
## 11.6.0 / 2026-09-08
|
|
5
22
|
### Fixed
|
|
6
23
|
* `NdrImport::File::SevenZip` was extracting files one directory level too deep
|
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# NdrImport [](https://github.com/NHSDigital/ndr_import/actions?query=workflow%3Atest) [](https://rubygems.org/gems/ndr_import) [](https://www.rubydoc.info/gems/ndr_import)
|
|
2
2
|
This is the NHS Digital (NHSD) National Disease Registers (NDR) Import ETL ruby gem, providing:
|
|
3
3
|
|
|
4
|
-
1. file import handlers for *extracting* data from delimited files (csv, pipe, tab, thorn), JSON Lines, .xls(x) spreadsheets, .doc(x) word documents, PDF, PDF AcroForms, XML, 7-Zip, Zip, avro and VCF files.
|
|
4
|
+
1. file import handlers for *extracting* data from delimited files (csv, pipe, tab, thorn), JSON Lines, .xls(x) spreadsheets, .doc(x) word documents, PDF, PDF AcroForms, XML, 7-Zip, Zip, gzip, avro and VCF files.
|
|
5
5
|
2. table mappers for *transforming* tabular and non-tabular data into key value pairs grouped by a common "klass".
|
|
6
6
|
|
|
7
7
|
## Installation
|
data/lib/ndr_import/file/all.rb
CHANGED
data/lib/ndr_import/file/base.rb
CHANGED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'securerandom'
|
|
2
|
+
require 'zlib'
|
|
3
|
+
require 'ndr_support/safe_file'
|
|
4
|
+
require_relative 'registry'
|
|
5
|
+
|
|
6
|
+
module NdrImport
|
|
7
|
+
# This is one of a collection of file handlers that deal with individual formats of data.
|
|
8
|
+
# They can be instantiated directly or via the factory method Registry.tables
|
|
9
|
+
module File
|
|
10
|
+
# This class is a gzip file handler that returns tables from the decompressed file. It also
|
|
11
|
+
# handles bgzip files (e.g. .vcf.gz), which are a series of gzip members.
|
|
12
|
+
class Gzip < Base
|
|
13
|
+
def initialize(filename, format, options = {})
|
|
14
|
+
super
|
|
15
|
+
@unzip_path = options['unzip_path']
|
|
16
|
+
|
|
17
|
+
validate_unzip_path_is_safe!
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def files(&block)
|
|
21
|
+
fail 'Not allowed in external environment' if defined?(::Rails) && ::Rails.env.external?
|
|
22
|
+
|
|
23
|
+
return enum_for(:files) unless block
|
|
24
|
+
|
|
25
|
+
destination = unique_destination
|
|
26
|
+
FileUtils.mkdir_p(SafeFile.safepath_to_string(destination))
|
|
27
|
+
|
|
28
|
+
# e.g. sample.vcf.gz is decompressed to sample.vcf
|
|
29
|
+
basename = ::File.basename(SafeFile.safepath_to_string(@filename), '.gz')
|
|
30
|
+
decompressed_filename = destination.join(basename)
|
|
31
|
+
decompress(decompressed_filename)
|
|
32
|
+
|
|
33
|
+
Registry.files(decompressed_filename, @options).each(&block)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Gzip files produce files, never tables.
|
|
37
|
+
def tables
|
|
38
|
+
fail 'Gzip#tables should never be called'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
# A new folder to decompress into. The time alone isn't unique: two decompressions in the
|
|
44
|
+
# same millisecond (e.g. consecutive tests, or two imports) would share a folder and collide.
|
|
45
|
+
def unique_destination
|
|
46
|
+
@unzip_path.join("#{Time.current.strftime('%H%M%S%L')}_#{SecureRandom.hex(4)}")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# zcat reads every gzip member. GzipReader#read stops after the first, which would silently
|
|
50
|
+
# read only the first block of a bgzip file.
|
|
51
|
+
def decompress(decompressed_filename)
|
|
52
|
+
::File.open(SafeFile.safepath_to_string(@filename), 'rb') do |input|
|
|
53
|
+
::File.open(SafeFile.safepath_to_string(decompressed_filename), 'wb') do |output|
|
|
54
|
+
Zlib::GzipReader.zcat(input) { |chunk| output.write(chunk) }
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def validate_unzip_path_is_safe!
|
|
60
|
+
SafeFile.safepath_to_string(@unzip_path)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
Registry.register(Gzip, 'gz')
|
|
65
|
+
end
|
|
66
|
+
end
|
data/lib/ndr_import/file/zip.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'securerandom'
|
|
1
2
|
require 'zip'
|
|
2
3
|
require 'ndr_support/safe_file'
|
|
3
4
|
require_relative 'registry'
|
|
@@ -21,7 +22,7 @@ module NdrImport
|
|
|
21
22
|
|
|
22
23
|
return enum_for(:files) unless block
|
|
23
24
|
|
|
24
|
-
destination =
|
|
25
|
+
destination = unique_destination
|
|
25
26
|
FileUtils.mkdir_p(SafeFile.safepath_to_string(destination))
|
|
26
27
|
|
|
27
28
|
::Zip::File.open(SafeFile.safepath_to_string(@filename)) do |zipfile|
|
|
@@ -36,6 +37,12 @@ module NdrImport
|
|
|
36
37
|
|
|
37
38
|
private
|
|
38
39
|
|
|
40
|
+
# A new folder to extract into. The time alone isn't unique: two extractions in the same
|
|
41
|
+
# millisecond (e.g. consecutive tests, or two imports) would share a folder and collide.
|
|
42
|
+
def unique_destination
|
|
43
|
+
@unzip_path.join("#{Time.current.strftime('%H%M%S%L')}_#{SecureRandom.hex(4)}")
|
|
44
|
+
end
|
|
45
|
+
|
|
39
46
|
# Unzip the zip file entry and enumerate over it
|
|
40
47
|
def unzip_entries(zipfile, destination, &block)
|
|
41
48
|
zipfile.entries.each do |entry|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require 'ndr_support/safe_file'
|
|
2
|
-
require 'ndr_import/
|
|
2
|
+
require 'ndr_import/csv_cell'
|
|
3
3
|
|
|
4
4
|
module NdrImport
|
|
5
5
|
module Helpers
|
|
@@ -81,7 +81,7 @@ module NdrImport
|
|
|
81
81
|
next if e.message =~ /invalid multibyte character/ # This encoding didn't work
|
|
82
82
|
|
|
83
83
|
raise(e)
|
|
84
|
-
rescue
|
|
84
|
+
rescue CSV::MalformedCSVError => e
|
|
85
85
|
next if e.message =~ /Invalid byte sequence/ # This encoding didn't work
|
|
86
86
|
|
|
87
87
|
raise malformed_csv_error(e, col_sep, row_num + 1, safe_path)
|
data/lib/ndr_import/table.rb
CHANGED
|
@@ -50,6 +50,7 @@ module NdrImport
|
|
|
50
50
|
@row_index = 0
|
|
51
51
|
@header_valid = false
|
|
52
52
|
@header_best_guess = nil
|
|
53
|
+
reset_regexp_columns
|
|
53
54
|
@notifier.try(:started)
|
|
54
55
|
|
|
55
56
|
last_col = last_column_to_transform
|
|
@@ -80,13 +81,19 @@ module NdrImport
|
|
|
80
81
|
@notifier.try(:processed, @row_index)
|
|
81
82
|
end
|
|
82
83
|
|
|
83
|
-
# Update 'column' values expressed as a regular expression
|
|
84
|
+
# Update 'column' values expressed as a regular expression to the header they match in this
|
|
85
|
+
# file. The patterns themselves are kept (see regexp_column_patterns), so the next file is
|
|
86
|
+
# matched afresh.
|
|
84
87
|
def mutate_regexp_columns(line)
|
|
85
|
-
|
|
86
|
-
next unless column['column'].is_a? Regexp
|
|
88
|
+
return if regexp_column_patterns.empty?
|
|
87
89
|
|
|
88
|
-
|
|
90
|
+
@columns = @columns.each_with_index.map do |column, index|
|
|
91
|
+
pattern = regexp_column_patterns[index]
|
|
92
|
+
next column unless pattern && line[index].to_s.match?(pattern)
|
|
93
|
+
|
|
94
|
+
column.merge('column' => line[index])
|
|
89
95
|
end
|
|
96
|
+
@masked_mappings = nil
|
|
90
97
|
end
|
|
91
98
|
|
|
92
99
|
# This method transforms an incoming line of data by applying each of the klass masked
|
|
@@ -120,11 +127,40 @@ module NdrImport
|
|
|
120
127
|
value = send(option)
|
|
121
128
|
coder[option] = value if value
|
|
122
129
|
end
|
|
123
|
-
coder['columns'] =
|
|
130
|
+
coder['columns'] = columns_with_regexp_patterns
|
|
124
131
|
end
|
|
125
132
|
|
|
126
133
|
private
|
|
127
134
|
|
|
135
|
+
# The 'column' values given as regular expressions, by column index, captured before any
|
|
136
|
+
# are replaced with a matched header. Memoised lazily rather than in initialize, so it also
|
|
137
|
+
# works for tables loaded from YAML, which don't call initialize.
|
|
138
|
+
def regexp_column_patterns
|
|
139
|
+
@regexp_column_patterns ||=
|
|
140
|
+
Array(@columns).each_with_index.with_object({}) do |(column, index), patterns|
|
|
141
|
+
patterns[index] = column['column'] if column && column['column'].is_a?(Regexp)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Puts the original regular expressions back, so a new file is matched against them
|
|
146
|
+
def reset_regexp_columns
|
|
147
|
+
return if regexp_column_patterns.empty?
|
|
148
|
+
|
|
149
|
+
@columns = columns_with_regexp_patterns
|
|
150
|
+
@masked_mappings = nil
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# The columns, with any 'column' values given as regular expressions restored. Unchanged
|
|
154
|
+
# (including nil, for a table with no columns) when there are none.
|
|
155
|
+
def columns_with_regexp_patterns
|
|
156
|
+
return @columns if regexp_column_patterns.empty?
|
|
157
|
+
|
|
158
|
+
Array(@columns).each_with_index.map do |column, index|
|
|
159
|
+
pattern = regexp_column_patterns[index]
|
|
160
|
+
pattern ? column.merge('column' => pattern) : column
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
128
164
|
# This method uses a buffer to not yield the last <buffer_size> iterations of an enumerable.
|
|
129
165
|
# We use it to skip footer lines (without having to convert the enumerable to an array).
|
|
130
166
|
def skip_footer_lines(lines, buffer_size)
|
|
@@ -237,7 +273,10 @@ module NdrImport
|
|
|
237
273
|
|
|
238
274
|
# returns the column names as we expect to receive them
|
|
239
275
|
def column_names(column_mappings)
|
|
240
|
-
column_mappings.map
|
|
276
|
+
column_mappings.map do |c|
|
|
277
|
+
name = c['column'] || c['standard_mapping']
|
|
278
|
+
name.to_s.downcase unless name.is_a?(Regexp)
|
|
279
|
+
end
|
|
241
280
|
end
|
|
242
281
|
|
|
243
282
|
# If specified in the mapping, stop transforming data at a given index (column)
|
|
@@ -83,7 +83,28 @@ module NdrImport
|
|
|
83
83
|
# Merge file_metadata (from VCF or XML) with directly assigned table_metadata
|
|
84
84
|
# to form `table_metadata`
|
|
85
85
|
mapping.table_metadata = (mapping.table_metadata || {}).merge(file_metadata || {})
|
|
86
|
-
|
|
86
|
+
|
|
87
|
+
augmented_table_content = filename_augmented_rows(mapping, table_content, filename)
|
|
88
|
+
|
|
89
|
+
yield(mapping, augmented_table_content)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def filename_augmented_rows(table, rows, filename)
|
|
94
|
+
return enum_for(:filename_augmented_rows, table, rows, filename) unless block_given?
|
|
95
|
+
|
|
96
|
+
filename_column_position = table.columns.index { |c| c['column'] == :filename }
|
|
97
|
+
|
|
98
|
+
rows.each.with_index do |row, i|
|
|
99
|
+
if filename_column_position
|
|
100
|
+
if i < table.header_lines
|
|
101
|
+
row.insert(filename_column_position, :filename)
|
|
102
|
+
else
|
|
103
|
+
row.insert(filename_column_position, ::File.basename(filename))
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
yield row
|
|
87
108
|
end
|
|
88
109
|
end
|
|
89
110
|
|
data/lib/ndr_import/vcf/table.rb
CHANGED
|
@@ -5,10 +5,14 @@ module NdrImport
|
|
|
5
5
|
# Syntatic sugar to ensure `header_lines` and `footer_lines` are 1 and 0 respectively.
|
|
6
6
|
# All other Table logic is inherited from `NdrImport::Table`
|
|
7
7
|
class Table < ::NdrImport::Table
|
|
8
|
+
VCF_OPTIONS = %w[vcf_file_metadata].freeze
|
|
9
|
+
|
|
8
10
|
def self.all_valid_options
|
|
9
|
-
super - %w[delimiter header_lines footer_lines] +
|
|
11
|
+
super - %w[delimiter header_lines footer_lines] + VCF_OPTIONS
|
|
10
12
|
end
|
|
11
13
|
|
|
14
|
+
attr_reader(*VCF_OPTIONS)
|
|
15
|
+
|
|
12
16
|
def header_lines
|
|
13
17
|
1
|
|
14
18
|
end
|
data/lib/ndr_import/version.rb
CHANGED
data/lib/ndr_import.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ndr_import
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 11.
|
|
4
|
+
version: 11.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- NCRS Development Team
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: exe
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2026-11-04 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: activemodel
|
|
@@ -29,7 +30,7 @@ dependencies:
|
|
|
29
30
|
requirements:
|
|
30
31
|
- - ">="
|
|
31
32
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '
|
|
33
|
+
version: '8.0'
|
|
33
34
|
- - "<"
|
|
34
35
|
- !ruby/object:Gem::Version
|
|
35
36
|
version: '8.2'
|
|
@@ -39,7 +40,7 @@ dependencies:
|
|
|
39
40
|
requirements:
|
|
40
41
|
- - ">="
|
|
41
42
|
- !ruby/object:Gem::Version
|
|
42
|
-
version: '
|
|
43
|
+
version: '8.0'
|
|
43
44
|
- - "<"
|
|
44
45
|
- !ruby/object:Gem::Version
|
|
45
46
|
version: '8.2'
|
|
@@ -89,7 +90,7 @@ dependencies:
|
|
|
89
90
|
requirements:
|
|
90
91
|
- - ">="
|
|
91
92
|
- !ruby/object:Gem::Version
|
|
92
|
-
version: '2.
|
|
93
|
+
version: '2.4'
|
|
93
94
|
- - "<"
|
|
94
95
|
- !ruby/object:Gem::Version
|
|
95
96
|
version: '4'
|
|
@@ -99,7 +100,7 @@ dependencies:
|
|
|
99
100
|
requirements:
|
|
100
101
|
- - ">="
|
|
101
102
|
- !ruby/object:Gem::Version
|
|
102
|
-
version: '2.
|
|
103
|
+
version: '2.4'
|
|
103
104
|
- - "<"
|
|
104
105
|
- !ruby/object:Gem::Version
|
|
105
106
|
version: '4'
|
|
@@ -107,16 +108,22 @@ dependencies:
|
|
|
107
108
|
name: avro
|
|
108
109
|
requirement: !ruby/object:Gem::Requirement
|
|
109
110
|
requirements:
|
|
110
|
-
- - "
|
|
111
|
+
- - ">="
|
|
111
112
|
- !ruby/object:Gem::Version
|
|
112
113
|
version: 1.11.0
|
|
114
|
+
- - "<"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '1.13'
|
|
113
117
|
type: :runtime
|
|
114
118
|
prerelease: false
|
|
115
119
|
version_requirements: !ruby/object:Gem::Requirement
|
|
116
120
|
requirements:
|
|
117
|
-
- - "
|
|
121
|
+
- - ">="
|
|
118
122
|
- !ruby/object:Gem::Version
|
|
119
123
|
version: 1.11.0
|
|
124
|
+
- - "<"
|
|
125
|
+
- !ruby/object:Gem::Version
|
|
126
|
+
version: '1.13'
|
|
120
127
|
- !ruby/object:Gem::Dependency
|
|
121
128
|
name: bio-vcf
|
|
122
129
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -284,21 +291,21 @@ dependencies:
|
|
|
284
291
|
- !ruby/object:Gem::Version
|
|
285
292
|
version: '0'
|
|
286
293
|
- !ruby/object:Gem::Dependency
|
|
287
|
-
name:
|
|
294
|
+
name: guard
|
|
288
295
|
requirement: !ruby/object:Gem::Requirement
|
|
289
296
|
requirements:
|
|
290
297
|
- - ">="
|
|
291
298
|
- !ruby/object:Gem::Version
|
|
292
|
-
version:
|
|
299
|
+
version: '0'
|
|
293
300
|
type: :development
|
|
294
301
|
prerelease: false
|
|
295
302
|
version_requirements: !ruby/object:Gem::Requirement
|
|
296
303
|
requirements:
|
|
297
304
|
- - ">="
|
|
298
305
|
- !ruby/object:Gem::Version
|
|
299
|
-
version:
|
|
306
|
+
version: '0'
|
|
300
307
|
- !ruby/object:Gem::Dependency
|
|
301
|
-
name:
|
|
308
|
+
name: guard-rubocop
|
|
302
309
|
requirement: !ruby/object:Gem::Requirement
|
|
303
310
|
requirements:
|
|
304
311
|
- - ">="
|
|
@@ -312,7 +319,7 @@ dependencies:
|
|
|
312
319
|
- !ruby/object:Gem::Version
|
|
313
320
|
version: '0'
|
|
314
321
|
- !ruby/object:Gem::Dependency
|
|
315
|
-
name:
|
|
322
|
+
name: guard-test
|
|
316
323
|
requirement: !ruby/object:Gem::Requirement
|
|
317
324
|
requirements:
|
|
318
325
|
- - ">="
|
|
@@ -326,21 +333,21 @@ dependencies:
|
|
|
326
333
|
- !ruby/object:Gem::Version
|
|
327
334
|
version: '0'
|
|
328
335
|
- !ruby/object:Gem::Dependency
|
|
329
|
-
name:
|
|
336
|
+
name: minitest
|
|
330
337
|
requirement: !ruby/object:Gem::Requirement
|
|
331
338
|
requirements:
|
|
332
339
|
- - ">="
|
|
333
340
|
- !ruby/object:Gem::Version
|
|
334
|
-
version:
|
|
341
|
+
version: '0'
|
|
335
342
|
type: :development
|
|
336
343
|
prerelease: false
|
|
337
344
|
version_requirements: !ruby/object:Gem::Requirement
|
|
338
345
|
requirements:
|
|
339
346
|
- - ">="
|
|
340
347
|
- !ruby/object:Gem::Version
|
|
341
|
-
version:
|
|
348
|
+
version: '0'
|
|
342
349
|
- !ruby/object:Gem::Dependency
|
|
343
|
-
name:
|
|
350
|
+
name: mocha
|
|
344
351
|
requirement: !ruby/object:Gem::Requirement
|
|
345
352
|
requirements:
|
|
346
353
|
- - ">="
|
|
@@ -354,35 +361,35 @@ dependencies:
|
|
|
354
361
|
- !ruby/object:Gem::Version
|
|
355
362
|
version: '0'
|
|
356
363
|
- !ruby/object:Gem::Dependency
|
|
357
|
-
name:
|
|
364
|
+
name: ndr_dev_support
|
|
358
365
|
requirement: !ruby/object:Gem::Requirement
|
|
359
366
|
requirements:
|
|
360
367
|
- - ">="
|
|
361
368
|
- !ruby/object:Gem::Version
|
|
362
|
-
version:
|
|
369
|
+
version: 3.1.3
|
|
363
370
|
type: :development
|
|
364
371
|
prerelease: false
|
|
365
372
|
version_requirements: !ruby/object:Gem::Requirement
|
|
366
373
|
requirements:
|
|
367
374
|
- - ">="
|
|
368
375
|
- !ruby/object:Gem::Version
|
|
369
|
-
version:
|
|
376
|
+
version: 3.1.3
|
|
370
377
|
- !ruby/object:Gem::Dependency
|
|
371
|
-
name:
|
|
378
|
+
name: rake
|
|
372
379
|
requirement: !ruby/object:Gem::Requirement
|
|
373
380
|
requirements:
|
|
374
381
|
- - ">="
|
|
375
382
|
- !ruby/object:Gem::Version
|
|
376
|
-
version:
|
|
383
|
+
version: 12.3.3
|
|
377
384
|
type: :development
|
|
378
385
|
prerelease: false
|
|
379
386
|
version_requirements: !ruby/object:Gem::Requirement
|
|
380
387
|
requirements:
|
|
381
388
|
- - ">="
|
|
382
389
|
- !ruby/object:Gem::Version
|
|
383
|
-
version:
|
|
390
|
+
version: 12.3.3
|
|
384
391
|
- !ruby/object:Gem::Dependency
|
|
385
|
-
name:
|
|
392
|
+
name: simplecov
|
|
386
393
|
requirement: !ruby/object:Gem::Requirement
|
|
387
394
|
requirements:
|
|
388
395
|
- - ">="
|
|
@@ -396,7 +403,7 @@ dependencies:
|
|
|
396
403
|
- !ruby/object:Gem::Version
|
|
397
404
|
version: '0'
|
|
398
405
|
- !ruby/object:Gem::Dependency
|
|
399
|
-
name:
|
|
406
|
+
name: terminal-notifier-guard
|
|
400
407
|
requirement: !ruby/object:Gem::Requirement
|
|
401
408
|
requirements:
|
|
402
409
|
- - ">="
|
|
@@ -430,7 +437,7 @@ files:
|
|
|
430
437
|
- lib/ndr_import.rb
|
|
431
438
|
- lib/ndr_import/acroform_reader.rb
|
|
432
439
|
- lib/ndr_import/avro/table.rb
|
|
433
|
-
- lib/ndr_import/
|
|
440
|
+
- lib/ndr_import/csv_cell.rb
|
|
434
441
|
- lib/ndr_import/file/acro_form.rb
|
|
435
442
|
- lib/ndr_import/file/all.rb
|
|
436
443
|
- lib/ndr_import/file/avro.rb
|
|
@@ -438,6 +445,7 @@ files:
|
|
|
438
445
|
- lib/ndr_import/file/delimited.rb
|
|
439
446
|
- lib/ndr_import/file/docx.rb
|
|
440
447
|
- lib/ndr_import/file/excel.rb
|
|
448
|
+
- lib/ndr_import/file/gzip.rb
|
|
441
449
|
- lib/ndr_import/file/json_lines.rb
|
|
442
450
|
- lib/ndr_import/file/office_file_helper.rb
|
|
443
451
|
- lib/ndr_import/file/pdf.rb
|
|
@@ -482,6 +490,7 @@ homepage: https://github.com/NHSDigital/ndr_import
|
|
|
482
490
|
licenses:
|
|
483
491
|
- MIT
|
|
484
492
|
metadata: {}
|
|
493
|
+
post_install_message:
|
|
485
494
|
rdoc_options: []
|
|
486
495
|
require_paths:
|
|
487
496
|
- lib
|
|
@@ -496,7 +505,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
496
505
|
- !ruby/object:Gem::Version
|
|
497
506
|
version: '0'
|
|
498
507
|
requirements: []
|
|
499
|
-
rubygems_version: 3.
|
|
508
|
+
rubygems_version: 3.5.22
|
|
509
|
+
signing_key:
|
|
500
510
|
specification_version: 4
|
|
501
511
|
summary: NDR Import
|
|
502
512
|
test_files: []
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
# This file allows us to choose the CSV library we want to use.
|
|
2
|
-
|
|
3
|
-
require 'csv'
|
|
4
|
-
require 'active_support/deprecation'
|
|
5
|
-
|
|
6
|
-
# Using relevant core CSV library.
|
|
7
|
-
class CSVLibrary < CSV; end
|
|
8
|
-
|
|
9
|
-
class << CSVLibrary
|
|
10
|
-
# Is the library we're using FasterCSV?
|
|
11
|
-
def fastercsv?
|
|
12
|
-
deprecate('if you desparately want fastercsv, please use it explicitly')
|
|
13
|
-
not self.const_defined?(:Reader)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# Ensure that we can pass "mode" straight through the underlying IO object
|
|
17
|
-
#
|
|
18
|
-
# Note: this could likely be refactored now, as upstream support for something
|
|
19
|
-
# very similar was added:
|
|
20
|
-
#
|
|
21
|
-
# https://github.com/ruby/csv/commit/b4edaf2cf1aa36f5c6264c07514b66739b87ceee
|
|
22
|
-
#
|
|
23
|
-
def foreach(path, **options, &block)
|
|
24
|
-
deprecate('CSV#foreach exists, with an optional `mode` argument')
|
|
25
|
-
return to_enum(__method__, path, **options) unless block
|
|
26
|
-
open(path, options.delete(:mode) || 'r', **options) do |csv|
|
|
27
|
-
csv.each(&block)
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def write_csv_to_string(data)
|
|
32
|
-
deprecate('write_csv_to_string -> generate')
|
|
33
|
-
self.generate do |csv|
|
|
34
|
-
data.each { |line| csv << line }
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def write_csv_to_file(data, filepath, mode = 'w')
|
|
39
|
-
deprecate('write_csv_to_file -> open')
|
|
40
|
-
self.open(filepath, mode) do |csv|
|
|
41
|
-
data.each { |line| csv << line }
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def read_csv_from_file(filepath)
|
|
46
|
-
deprecate('read_csv_from_file -> read')
|
|
47
|
-
self.read(filepath)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
private
|
|
51
|
-
|
|
52
|
-
def deprecator
|
|
53
|
-
@deprecator ||= ActiveSupport::Deprecation.new(NdrImport::VERSION, 'NdrImport')
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def deprecate(additional_message = nil)
|
|
57
|
-
deprecator.warn(<<~MESSAGE)
|
|
58
|
-
CSVLibrary is deprecated, and will be removed in a future version of ndr_import.
|
|
59
|
-
Please use standard functionality provided by Ruby's CSV library (#{additional_message}).
|
|
60
|
-
MESSAGE
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# Forward port CSV::Cell, as it is sometimes
|
|
65
|
-
# serialised in YAML. :-(
|
|
66
|
-
class CSV::Cell < String
|
|
67
|
-
def initialize(data = '', is_null = false)
|
|
68
|
-
super(is_null ? '' : data)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def data
|
|
72
|
-
to_s
|
|
73
|
-
end
|
|
74
|
-
end
|