inferno_core 0.6.14 → 0.6.16

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 38e171c150a97606bbe4f6bc0c52774510057ac23d3c05b4180781f7ba73c429
4
- data.tar.gz: ab5cb618341fec45b35d55349a9138c9a544d37327fd8bd971dbb9c8c6049e15
3
+ metadata.gz: bdded0041b27a81a8cedae003b073e738a719eda6671cb39b1556bd165a986c9
4
+ data.tar.gz: f9cb54ff76488ce34f8f9c9464bbc3588f67f3931d6eef284a78d1af32a0b78e
5
5
  SHA512:
6
- metadata.gz: adea4c5a64ebc33389fd628cca27bc8e275d45d59611a60cb3c3d85be69b168da6f58e7e02647486ee8155c6bd258b6cd284648260b7d689c308dc9590ee2783
7
- data.tar.gz: d9b9973007a9f1e2f1064945456ac0b2fbfe94359d33c3b84119bfe7b391c08b2d085d22cf9823ce61466d249cdea0f552b4caee6fb37cf56650bd190f324341
6
+ metadata.gz: e53518c76be16a5cc631a503c84388b706d2030a30469048379f3b4d91d1525d5e1ee373cb454c191b97eb857c9682d821270c9c2a35cfe408b5fd7fa405a236
7
+ data.tar.gz: a078da89879d42f3cda28ebc8dca66feca2a85e9f735868bbcd4dbf70774ef268e613fd4aad4fe076002af1d3d7035bd02de8c2679d2ce17b8ee05a794f629ab
@@ -112,7 +112,7 @@ module Inferno
112
112
  Inferno::DSL::FHIRResourceValidation::Validator.new(:default, 'evaluator_cli') do
113
113
  igs(ig_path)
114
114
 
115
- cli_context do
115
+ validation_context do
116
116
  # For our purposes, code display mismatches should be warnings and not affect profile conformance
117
117
  displayWarnings(true)
118
118
  end
@@ -12,6 +12,9 @@ module Inferno
12
12
  LONGDESC
13
13
  def export_csv
14
14
  ENV['NO_DB'] = 'true'
15
+
16
+ require_relative '../../../inferno'
17
+
15
18
  RequirementsExporter.new.run
16
19
  end
17
20
 
@@ -22,6 +25,11 @@ module Inferno
22
25
  LONGDESC
23
26
  def check
24
27
  ENV['NO_DB'] = 'true'
28
+
29
+ require_relative '../../../inferno'
30
+
31
+ Inferno::Application.start(:requirements)
32
+
25
33
  RequirementsExporter.new.run_check
26
34
  end
27
35
 
@@ -176,7 +176,7 @@ module Inferno
176
176
  if File.exist?(output_file_path)
177
177
  if old_csv == new_csv
178
178
  puts "'#{output_file_name}' file is up to date."
179
- return unless unmatched_requirement_ids.present?
179
+ return
180
180
  else
181
181
  puts <<~MESSAGE
182
182
  #{output_file_name} file is out of date.
@@ -70,21 +70,24 @@ module Inferno
70
70
  # requirement_set_id_2: [row1, row2, row 3, ...]
71
71
  # }
72
72
  def input_requirement_sets
73
- requirement_set_hash = Hash.new { |hash, key| hash[key] = [] }
74
- available_input_worksheets.each_with_object(requirement_set_hash) do |worksheet_file, requirement_sets|
75
- worksheet = Roo::Spreadsheet.open(worksheet_file)
76
- set_identifier = requirement_set_id(worksheet)
77
-
78
- CSV.parse(
79
- worksheet.sheet('Requirements').to_csv,
80
- headers: true
81
- ).each do |row|
82
- row_hash = row.to_h.slice(*INPUT_HEADERS)
83
- row_hash['Sub-Requirement(s)']&.delete_prefix!('mailto:')
84
-
85
- requirement_sets[set_identifier] << row_hash
73
+ @input_requirement_sets ||=
74
+ begin
75
+ requirement_set_hash = Hash.new { |hash, key| hash[key] = [] }
76
+ available_input_worksheets.each_with_object(requirement_set_hash) do |worksheet_file, requirement_sets|
77
+ worksheet = Roo::Spreadsheet.open(worksheet_file)
78
+ set_identifier = requirement_set_id(worksheet)
79
+
80
+ CSV.parse(
81
+ worksheet.sheet('Requirements').to_csv,
82
+ headers: true
83
+ ).each do |row|
84
+ row_hash = row.to_h.slice(*INPUT_HEADERS)
85
+ row_hash['Sub-Requirement(s)']&.delete_prefix!('mailto:')
86
+
87
+ requirement_sets[set_identifier] << row_hash
88
+ end
89
+ end
86
90
  end
87
- end
88
91
  end
89
92
 
90
93
  def new_requirements_csv # rubocop:disable Metrics/CyclomaticComplexity
@@ -125,6 +128,52 @@ module Inferno
125
128
  @old_requirements_csv ||= File.read(requirements_output_file_path)
126
129
  end
127
130
 
131
+ def missing_subrequirements
132
+ @missing_subrequirements =
133
+ {}.tap do |missing_requirements|
134
+ repo = Inferno::Repositories::Requirements.new
135
+
136
+ input_requirement_sets
137
+ .each do |requirement_set, requirements|
138
+ requirements.each do |requirement_hash|
139
+ missing_subrequirements =
140
+ Inferno::Entities::Requirement.expand_requirement_ids(requirement_hash['Sub-Requirement(s)'])
141
+ .reject { |requirement_id| repo.exists? requirement_id }
142
+
143
+ missing_subrequirements += missing_actor_subrequirements(requirement_hash['Sub-Requirement(s)'])
144
+
145
+ next if missing_subrequirements.blank?
146
+
147
+ id = "#{requirement_set}@#{requirement_hash['ID*']}"
148
+
149
+ missing_requirements[id] = missing_subrequirements
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ def missing_actor_subrequirements(subrequirement_string)
156
+ return [] if subrequirement_string.blank?
157
+
158
+ return [] unless subrequirement_string.include? '#'
159
+
160
+ subrequirement_string
161
+ .split(',')
162
+ .map(&:strip)
163
+ .select { |requirement_string| requirement_string.include? '#' }
164
+ .select do |requirement_string|
165
+ Inferno::Entities::Requirement.expand_requirement_ids(requirement_string).blank?
166
+ end
167
+ end
168
+
169
+ def check_subrequirements
170
+ return if missing_subrequirements.blank?
171
+
172
+ missing_subrequirements.each do |id, subrequirement_ids|
173
+ puts "#{id} is missing the following sub-requirements:\n #{subrequirement_ids.join(', ')}"
174
+ end
175
+ end
176
+
128
177
  def run
129
178
  check_presence_of_input_files
130
179
 
@@ -147,6 +196,10 @@ module Inferno
147
196
  File.write(requirements_output_file_path, new_requirements_csv, encoding: Encoding::UTF_8)
148
197
  end
149
198
 
199
+ Inferno::Application.start(:requirements)
200
+
201
+ check_subrequirements
202
+
150
203
  puts 'Done.'
151
204
  end
152
205
 
@@ -167,14 +220,20 @@ module Inferno
167
220
  false
168
221
  end
169
222
 
170
- return if requirements_ok
223
+ unless requirements_ok
224
+ puts <<~MESSAGE
225
+ Check Failed. To resolve, run:
226
+
227
+ bundle exec inferno requirements export_csv
228
+
229
+ MESSAGE
230
+ exit(1)
231
+ end
171
232
 
172
- puts <<~MESSAGE
173
- Check Failed. To resolve, run:
233
+ check_subrequirements
174
234
 
175
- bundle exec inferno requirements export_csv
235
+ return if missing_subrequirements.blank?
176
236
 
177
- MESSAGE
178
237
  exit(1)
179
238
  end
180
239
 
@@ -9,7 +9,7 @@ module Inferno
9
9
  field :requirement
10
10
  field :conformance
11
11
  field :actors
12
- field :sub_requirements
12
+ field :subrequirements
13
13
  field :conditionality
14
14
  field :url, if: :field_present?
15
15
  field :not_tested_reason, if: :field_present?
@@ -66,8 +66,9 @@ module Inferno
66
66
  # Validate a FHIR resource
67
67
  #
68
68
  # @param resource [FHIR::Model]
69
- # @param profile_url [String] url of the profile to validate against,
70
- # defaults to validating against the base FHIR resource
69
+ # @param profile_url [String] canonical url of the profile to validate against,
70
+ # may include a version separated by a vertical bar (|),
71
+ # and defaults to validating against the base FHIR resource type
71
72
  # @param validator [Symbol] the name of the validator to use
72
73
  # @return [void]
73
74
  def assert_valid_resource(resource: self.resource, profile_url: nil, validator: :default)
@@ -147,7 +147,7 @@ module Inferno
147
147
  end
148
148
 
149
149
  def matching_pattern_identifier_slice?(slice, discriminator)
150
- slice.identifier.system == discriminator[:system]
150
+ slice.system == discriminator[:system]
151
151
  end
152
152
 
153
153
  def matching_value_slice?(slice, discriminator)
@@ -1,4 +1,5 @@
1
1
  require_relative '../ext/fhir_models'
2
+ require_relative '../feature'
2
3
  module Inferno
3
4
  module DSL
4
5
  # This module contains the methods needed to configure a validator to
@@ -19,7 +20,7 @@ module Inferno
19
20
  # { type: 'info', message: 'everything is ok' }
20
21
  # end
21
22
  # end
22
- # cli_context do
23
+ # validation_context do
23
24
  # noExtensibleBindingMessages true
24
25
  # allowExampleUrls true
25
26
  # txServer nil
@@ -74,12 +75,12 @@ module Inferno
74
75
  # igs("hl7.fhir.us.core#3.1.1", "hl7.fhir.us.core#6.0.0")
75
76
  # @param validator_igs [Array<String>]
76
77
  def igs(*validator_igs)
77
- cli_context(igs: validator_igs) if validator_igs.any?
78
+ validation_context(igs: validator_igs) if validator_igs.any?
78
79
 
79
- cli_context.igs
80
+ validation_context.igs
80
81
  end
81
82
 
82
- # Set the cliContext used as part of each validation request.
83
+ # Set the validationContext used as part of each validation request.
83
84
  # Fields may be passed as either a Hash or block.
84
85
  # Note that all fields included here will be sent directly in requests,
85
86
  # there is no check that the fields are correct.
@@ -88,7 +89,7 @@ module Inferno
88
89
  # # Passing fields in a block
89
90
  # fhir_resource_validator do
90
91
  # url 'http://example.com/validator'
91
- # cli_context do
92
+ # validation_context do
92
93
  # noExtensibleBindingMessages true
93
94
  # allowExampleUrls true
94
95
  # txServer nil
@@ -99,7 +100,7 @@ module Inferno
99
100
  # # Passing fields in a Hash
100
101
  # fhir_resource_validator do
101
102
  # url 'http://example.org/validator'
102
- # cli_context({
103
+ # validation_context({
103
104
  # noExtensibleBindingMessages: true,
104
105
  # allowExampleUrls: true,
105
106
  # txServer: nil
@@ -107,19 +108,21 @@ module Inferno
107
108
  # end
108
109
  #
109
110
  # @param definition [Hash] raw fields to set, optional
110
- def cli_context(definition = nil, &)
111
- if @cli_context
111
+ def validation_context(definition = nil, &)
112
+ if @validation_context
112
113
  if definition
113
- @cli_context.definition.merge!(definition.deep_symbolize_keys)
114
+ @validation_context.definition.merge!(definition.deep_symbolize_keys)
114
115
  elsif block_given?
115
- @cli_context.instance_eval(&)
116
+ @validation_context.instance_eval(&)
116
117
  end
117
118
  else
118
- @cli_context = CliContext.new(definition || {}, &)
119
+ @validation_context = ValidationContext.new(definition || {}, &)
119
120
  end
120
- @cli_context
121
+ @validation_context
121
122
  end
122
123
 
124
+ alias cli_context validation_context
125
+
123
126
  # @private
124
127
  def additional_validations
125
128
  @additional_validations ||= []
@@ -268,9 +271,13 @@ module Inferno
268
271
 
269
272
  @session_id = validator_session_id if validator_session_id
270
273
 
274
+ # HL7 Validator Core 6.5.19+ renamed `cliContext` to `validationContext`.
275
+ # This allows backward compatibility until the validator-wrapper is updated.
276
+ context_key = Feature.use_validation_context_key? ? :validationContext : :cliContext
277
+
271
278
  wrapped_resource = {
272
- cliContext: {
273
- **cli_context.definition,
279
+ context_key => {
280
+ **validation_context.definition,
274
281
  profiles: [profile_url]
275
282
  },
276
283
  filesToValidate: [
@@ -365,10 +372,10 @@ module Inferno
365
372
  end
366
373
 
367
374
  # @private
368
- class CliContext
375
+ class ValidationContext
369
376
  attr_reader :definition
370
377
 
371
- CLICONTEXT_DEFAULTS = {
378
+ VALIDATIONCONTEXT_DEFAULTS = {
372
379
  sv: '4.0.1',
373
380
  doNative: false,
374
381
  extensions: ['any'],
@@ -377,13 +384,13 @@ module Inferno
377
384
 
378
385
  # @private
379
386
  def initialize(definition, &)
380
- @definition = CLICONTEXT_DEFAULTS.merge(definition.deep_symbolize_keys)
387
+ @definition = VALIDATIONCONTEXT_DEFAULTS.merge(definition.deep_symbolize_keys)
381
388
  instance_eval(&) if block_given?
382
389
  end
383
390
 
384
391
  # @private
385
392
  def method_missing(method_name, *args)
386
- # Interpret any other method as setting a field on cliContext.
393
+ # Interpret any other method as setting a field on validationContext.
387
394
  # Follow the same format as `Validator.url` here:
388
395
  # only set the value if one is provided.
389
396
  # args will be an empty array if no value is provided.
@@ -12,7 +12,8 @@ module Inferno
12
12
  :requirement,
13
13
  :conformance,
14
14
  :actors,
15
- :sub_requirements,
15
+ :subrequirements,
16
+ :subrequirements_string,
16
17
  :conditionality,
17
18
  :not_tested_reason,
18
19
  :not_tested_details
@@ -28,6 +29,10 @@ module Inferno
28
29
  self.requirement_set = id.split(/[@#]/).first
29
30
  end
30
31
 
32
+ def subrequirements
33
+ @subrequirements ||= self.class.expand_requirement_ids(subrequirements_string, requirement_set)
34
+ end
35
+
31
36
  # Expand a comma-delimited list of requirement id references into an Array
32
37
  # of full requirement ids
33
38
  #
@@ -62,7 +67,7 @@ module Inferno
62
67
  requirement_ids =
63
68
  if actor.present?
64
69
  return Repositories::Requirements.new.requirements_for_actor(current_set, actor).map(&:id)
65
- elsif requirement_string.include? '-'
70
+ elsif requirement_string.include?('-') && !requirement_string.match?(/[^\d\-]/)
66
71
  start_id, end_id = requirement_string.split('-')
67
72
  if start_id.match?(/^\d+$/) && end_id.match?(/^\d+$/)
68
73
  (start_id..end_id).to_a
@@ -4,6 +4,10 @@ module Inferno
4
4
  def requirements_enabled?
5
5
  ENV.fetch('ENABLE_REQUIREMENTS', 'false')&.casecmp?('true')
6
6
  end
7
+
8
+ def use_validation_context_key?
9
+ ENV.fetch('USE_VALIDATION_CONTEXT', 'false')&.casecmp?('true')
10
+ end
7
11
  end
8
12
  end
9
13
  end