inferno_core 0.5.3 → 0.5.4

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: '090f68164e2fc19d1f97f62dd0fb13c12c77eb12c29bb9b528c9b9cb56f48770'
4
- data.tar.gz: e239a1702ee11a85229db5355ad7c8a415d71b40018c052bb3e2c972c824d12c
3
+ metadata.gz: e11d6b274778016418f7189d8ec9e724cf20861c6e03385dc9c302299f198d18
4
+ data.tar.gz: '09c65484d51b2f7be0a3985b374d51593d59c432ba11c21bd10d54c798ccafa4'
5
5
  SHA512:
6
- metadata.gz: 2491100649bba23576a442fdeeef561b407e5f7b0b89fbd0827b55ced37e1dcf29c1f5b908c316e44c38301a74d760b5fa8bba4b2cfdf5e039d36fab4c3c181f
7
- data.tar.gz: e05eb12863387acecd5782267f25700d3a2e233ed8f581bda98627a76822c33b5e6a1f0ed8e770a6a9d971c88be610453f0aac9a13245b8412f2cb7673431327
6
+ metadata.gz: 0daf93ce97d8a5a8e9b409200d7c001e4ac49107887db05073399a74795a94b449d3c1eb1d139214c1402e1ea10a954ee1271b80c642909c379cd7bb0ba7a1f0
7
+ data.tar.gz: 3a70bb18128af1494e0fcd1a023d8e18e8043dd535ae9c00f8471c8eb85e23678fa7c8bcb19591852c3593c6588ba92af206a90644cf6288659179fef98c1a41
@@ -1,14 +1,21 @@
1
1
  require_relative '../../../inferno/dsl/fhir_evaluation/evaluator'
2
+ require_relative '../../../inferno/entities'
3
+ require_relative '../../utils/ig_downloader'
4
+
5
+ require 'tempfile'
2
6
 
3
7
  module Inferno
4
8
  module CLI
5
- class Evaluate
6
- def run(ig_path, data_path, _log_level)
9
+ class Evaluate < Thor::Group
10
+ include Thor::Actions
11
+ include Inferno::Utils::IgDownloader
12
+
13
+ def evaluate(ig_path, data_path, _log_level)
7
14
  validate_args(ig_path, data_path)
15
+ _ig = get_ig(ig_path)
8
16
 
9
- # IG Import, rule execution, and result output below will be integrated at phase 2 and 3.
17
+ # Rule execution, and result output below will be integrated soon.
10
18
 
11
- # @ig = File.join(__dir__, 'ig', ig_path)
12
19
  # if data_path
13
20
  # DatasetLoader.from_path(File.join(__dir__, data_path))
14
21
  # else
@@ -30,6 +37,32 @@ module Inferno
30
37
  raise "Provided path '#{data_path}' is not a directory"
31
38
  end
32
39
 
40
+ def get_ig(ig_path)
41
+ if File.exist?(ig_path)
42
+ ig = Inferno::Entities::IG.from_file(ig_path)
43
+ elsif in_user_package_cache?(ig_path.sub('@', '#'))
44
+ # NPM syntax for a package identifier is id@version (eg, hl7.fhir.us.core@3.1.1)
45
+ # but in the cache the separator is # (hl7.fhir.us.core#3.1.1)
46
+ cache_directory = File.join(user_package_cache, ig_path.sub('@', '#'))
47
+ ig = Inferno::Entities::IG.from_file(cache_directory)
48
+ else
49
+ Tempfile.create('package.tgz') do |temp_file|
50
+ load_ig(ig_path, nil, { force: true }, temp_file.path)
51
+ ig = Inferno::Entities::IG.from_file(temp_file.path)
52
+ end
53
+ end
54
+ ig.add_self_to_repository
55
+ ig
56
+ end
57
+
58
+ def user_package_cache
59
+ File.join(Dir.home, '.fhir', 'packages')
60
+ end
61
+
62
+ def in_user_package_cache?(ig_identifier)
63
+ File.directory?(File.join(user_package_cache, ig_identifier))
64
+ end
65
+
33
66
  def output_results(results, output)
34
67
  if output&.end_with?('json')
35
68
  oo = FhirEvaluator::EvaluationResult.to_operation_outcome(results)
@@ -45,7 +45,7 @@ module Inferno
45
45
  type: :string,
46
46
  desc: 'Export evaluation result to outcome.json as an OperationOutcome'
47
47
  def evaluate(ig_path)
48
- Evaluate.new.run(ig_path, options[:data_path], Logger::INFO)
48
+ Evaluate.new.evaluate(ig_path, options[:data_path], Logger::INFO)
49
49
  end
50
50
 
51
51
  desc 'console', 'Start an interactive console session with Inferno'
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fhir_models'
4
+ require 'pathname'
5
+ require 'rubygems/package'
6
+ require 'zlib'
7
+
8
+ require_relative '../repositories/igs'
9
+
10
+ module Inferno
11
+ module Entities
12
+ # IG is a wrapper class around the relevant concepts inside an IG.
13
+ # Not everything within an IG is currently used by Inferno.
14
+ class IG < Entity
15
+ ATTRIBUTES = [
16
+ :id,
17
+ :profiles,
18
+ :extensions,
19
+ :value_sets,
20
+ :search_params,
21
+ :examples
22
+ ].freeze
23
+
24
+ include Inferno::Entities::Attributes
25
+
26
+ def initialize(**params)
27
+ super(params, ATTRIBUTES)
28
+
29
+ @profiles = []
30
+ @extensions = []
31
+ @value_sets = []
32
+ @examples = []
33
+ @search_params = []
34
+ end
35
+
36
+ def self.from_file(ig_path)
37
+ raise "#{ig_path} does not exist" unless File.exist?(ig_path)
38
+
39
+ # fhir_models by default logs the entire content of non-FHIR files
40
+ # which could be things like a package.json
41
+ original_logger = FHIR.logger
42
+ FHIR.logger = Logger.new('/dev/null')
43
+
44
+ if File.directory?(ig_path)
45
+ from_directory(ig_path)
46
+ elsif ig_path.end_with? '.tgz'
47
+ from_tgz(ig_path)
48
+ else
49
+ raise "Unable to load #{ig_path} as it does not appear to be a directory or a .tgz file"
50
+ end
51
+ ensure
52
+ FHIR.logger = original_logger if defined? original_logger
53
+ end
54
+
55
+ def self.from_tgz(ig_path)
56
+ tar = Gem::Package::TarReader.new(
57
+ Zlib::GzipReader.open(ig_path)
58
+ )
59
+
60
+ ig = IG.new
61
+
62
+ tar.each do |entry|
63
+ next if skip_item?(entry.full_name, entry.directory?)
64
+
65
+ begin
66
+ resource = FHIR::Json.from_json(entry.read)
67
+ next if resource.nil?
68
+
69
+ ig.handle_resource(resource, entry.full_name)
70
+ rescue StandardError
71
+ next
72
+ end
73
+ end
74
+ ig
75
+ end
76
+
77
+ def self.from_directory(ig_directory)
78
+ ig = IG.new
79
+
80
+ ig_path = Pathname.new(ig_directory)
81
+ Dir.glob("#{ig_path}/**/*") do |f|
82
+ relative_path = Pathname.new(f).relative_path_from(ig_path).to_s
83
+ next if skip_item?(relative_path, File.directory?(f))
84
+
85
+ begin
86
+ resource = FHIR::Json.from_json(File.read(f))
87
+ next if resource.nil?
88
+
89
+ ig.handle_resource(resource, relative_path)
90
+ rescue StandardError
91
+ next
92
+ end
93
+ end
94
+ ig
95
+ end
96
+
97
+ # These files aren't FHIR resources
98
+ FILES_TO_SKIP = ['package.json', 'validation-summary.json'].freeze
99
+
100
+ def self.skip_item?(relative_path, is_directory)
101
+ return true if is_directory
102
+
103
+ file_name = relative_path.split('/').last
104
+
105
+ return true unless file_name.end_with? '.json'
106
+ return true unless relative_path.start_with? 'package/'
107
+
108
+ return true if file_name.start_with? '.' # ignore hidden files
109
+ return true if file_name.end_with? '.openapi.json'
110
+ return true if FILES_TO_SKIP.include? file_name
111
+
112
+ false
113
+ end
114
+
115
+ def handle_resource(resource, relative_path)
116
+ case resource.resourceType
117
+ when 'StructureDefinition'
118
+ if resource.type == 'Extension'
119
+ extensions.push resource
120
+ else
121
+ profiles.push resource
122
+ end
123
+ when 'ValueSet'
124
+ value_sets.push resource
125
+ when 'SearchParameter'
126
+ search_params.push resource
127
+ when 'ImplementationGuide'
128
+ @id = extract_package_id(resource)
129
+ else
130
+ examples.push(resource) if relative_path.start_with? 'package/example'
131
+ end
132
+ end
133
+
134
+ def extract_package_id(ig_resource)
135
+ "#{ig_resource.id}##{ig_resource.version || 'current'}"
136
+ end
137
+
138
+ # @private
139
+ def add_self_to_repository
140
+ repository.insert(self)
141
+ end
142
+
143
+ # @private
144
+ def repository
145
+ Inferno::Repositories::IGs.new
146
+ end
147
+ end
148
+ end
149
+ end
@@ -2,6 +2,7 @@ require_relative 'entities/attributes'
2
2
  require_relative 'entities/has_runnable'
3
3
  require_relative 'entities/entity'
4
4
  require_relative 'entities/header'
5
+ require_relative 'entities/ig'
5
6
  require_relative 'entities/message'
6
7
  require_relative 'entities/request'
7
8
  require_relative 'entities/result'