proformaxml 1.2.0 → 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 606acc3bf478e597146722128fa681af0e50985af661a74d302de9c3ab2b5b37
4
- data.tar.gz: 474a73f7e5a09f850d9c8b9e5a4fb90b93953d2ceece434750f91f5a8581b633
3
+ metadata.gz: 4662b9372d02e7ffaf3c7ff7c444732c723d4f84109be5c82fc06a3cabf0cc0b
4
+ data.tar.gz: bc74cbb0142da68f39aa70a9e5c06ef7a2d1313540f120f1e393094c2cf84a81
5
5
  SHA512:
6
- metadata.gz: d482b1a2a9ad647fe971577eeb6e5d19210e08b51bcdab7cc2daecea68cd1cc1389b80ff9da2d75cf628dd36999241655549a29ad41c9c666a9db4c698a7216d
7
- data.tar.gz: d5b0f74efc13fda6dbf91d55799321d694db0961b9d80d07bed395e6f202a0dc8ba935a2437fac82f51d455623af7b208df0b2e3f9e3fc264f1763488ec42031
6
+ metadata.gz: 4ca4104cb636e4ea93c5c6456d5637919895f9ce616b05dc2f4564b17a5a70b9f441f62729025279b15a8b7ac1385d13a7165508bf7bec841bc4d788fc19e0a0
7
+ data.tar.gz: e24fe2ab9db3a08407e35f9ae01da9521e05e6a71c71c4f341de032428582e3cc0d7b4dca9db7f723f27a9789e28a6a7b2b552ad0f30b06835ba04901fa88b0c
data/.rubocop.yml CHANGED
@@ -13,7 +13,7 @@ inherit_from:
13
13
  - .rubocop/style.yml
14
14
 
15
15
  AllCops:
16
- TargetRubyVersion: 3.2
16
+ TargetRubyVersion: 3.3
17
17
  TargetRailsVersion: 7.0 # for ActiveSupport
18
18
  UseCache: True
19
19
  NewCops: enable
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- proformaxml (1.2.0)
4
+ proformaxml (1.3.0)
5
5
  activemodel (>= 5.2.3, < 8.0.0)
6
6
  activesupport (>= 5.2.3, < 8.0.0)
7
7
  dachsfisch (~> 1.0.0)
@@ -11,9 +11,9 @@ PATH
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- activemodel (7.1.1)
15
- activesupport (= 7.1.1)
16
- activesupport (7.1.1)
14
+ activemodel (7.1.3.2)
15
+ activesupport (= 7.1.3.2)
16
+ activesupport (7.1.3.2)
17
17
  base64
18
18
  bigdecimal
19
19
  concurrent-ruby (~> 1.0, >= 1.0.2)
@@ -24,21 +24,21 @@ GEM
24
24
  mutex_m
25
25
  tzinfo (~> 2.0)
26
26
  ast (2.4.2)
27
- base64 (0.1.1)
28
- bigdecimal (3.1.4)
27
+ base64 (0.2.0)
28
+ bigdecimal (3.1.6)
29
29
  byebug (11.1.3)
30
30
  coderay (1.1.3)
31
- concurrent-ruby (1.2.2)
31
+ concurrent-ruby (1.2.3)
32
32
  connection_pool (2.4.1)
33
33
  dachsfisch (1.0.0)
34
34
  nokogiri (>= 1.14.1, < 2.0.0)
35
- diff-lcs (1.5.0)
35
+ diff-lcs (1.5.1)
36
36
  docile (1.4.0)
37
- drb (2.1.1)
37
+ drb (2.2.0)
38
38
  ruby2_keywords
39
- factory_bot (6.3.0)
39
+ factory_bot (6.4.6)
40
40
  activesupport (>= 5.0.0)
41
- ffi (1.16.1)
41
+ ffi (1.16.3)
42
42
  formatador (1.1.0)
43
43
  guard (2.18.1)
44
44
  formatador (>= 0.2.4)
@@ -56,24 +56,24 @@ GEM
56
56
  rspec (>= 2.99.0, < 4.0)
57
57
  i18n (1.14.1)
58
58
  concurrent-ruby (~> 1.0)
59
- json (2.6.3)
59
+ json (2.7.1)
60
60
  language_server-protocol (3.17.0.3)
61
61
  listen (3.8.0)
62
62
  rb-fsevent (~> 0.10, >= 0.10.3)
63
63
  rb-inotify (~> 0.9, >= 0.9.10)
64
- lumberjack (1.2.9)
64
+ lumberjack (1.2.10)
65
65
  method_source (1.0.0)
66
- mini_portile2 (2.8.4)
67
- minitest (5.20.0)
68
- mutex_m (0.1.2)
66
+ mini_portile2 (2.8.5)
67
+ minitest (5.22.2)
68
+ mutex_m (0.2.0)
69
69
  nenv (0.3.0)
70
- nokogiri (1.15.4)
70
+ nokogiri (1.16.4)
71
71
  mini_portile2 (~> 2.8.2)
72
72
  racc (~> 1.4)
73
73
  notiffany (0.1.3)
74
74
  nenv (~> 0.1)
75
75
  shellany (~> 0.0)
76
- parallel (1.23.0)
76
+ parallel (1.24.0)
77
77
  parser (3.2.2.4)
78
78
  ast (~> 2.4.1)
79
79
  racc
@@ -83,34 +83,33 @@ GEM
83
83
  pry-byebug (3.10.1)
84
84
  byebug (~> 11.0)
85
85
  pry (>= 0.13, < 0.15)
86
- racc (1.7.1)
87
- rack (3.0.8)
86
+ racc (1.7.3)
87
+ rack (3.0.9.1)
88
88
  rainbow (3.1.1)
89
- rake (13.0.6)
89
+ rake (13.2.1)
90
90
  rb-fsevent (0.11.2)
91
91
  rb-inotify (0.10.1)
92
92
  ffi (~> 1.0)
93
- regexp_parser (2.8.2)
93
+ regexp_parser (2.8.3)
94
94
  rexml (3.2.6)
95
- rspec (3.12.0)
96
- rspec-core (~> 3.12.0)
97
- rspec-expectations (~> 3.12.0)
98
- rspec-mocks (~> 3.12.0)
95
+ rspec (3.13.0)
96
+ rspec-core (~> 3.13.0)
97
+ rspec-expectations (~> 3.13.0)
98
+ rspec-mocks (~> 3.13.0)
99
99
  rspec-collection_matchers (1.2.1)
100
100
  rspec-expectations (>= 2.99.0.beta1)
101
- rspec-core (3.12.2)
102
- rspec-support (~> 3.12.0)
103
- rspec-expectations (3.12.3)
101
+ rspec-core (3.13.0)
102
+ rspec-support (~> 3.13.0)
103
+ rspec-expectations (3.13.0)
104
104
  diff-lcs (>= 1.2.0, < 2.0)
105
- rspec-support (~> 3.12.0)
105
+ rspec-support (~> 3.13.0)
106
106
  rspec-github (2.4.0)
107
107
  rspec-core (~> 3.0)
108
- rspec-mocks (3.12.6)
108
+ rspec-mocks (3.13.0)
109
109
  diff-lcs (>= 1.2.0, < 2.0)
110
- rspec-support (~> 3.12.0)
111
- rspec-support (3.12.1)
112
- rubocop (1.57.1)
113
- base64 (~> 0.1.1)
110
+ rspec-support (~> 3.13.0)
111
+ rspec-support (3.13.0)
112
+ rubocop (1.59.0)
114
113
  json (~> 2.3)
115
114
  language_server-protocol (>= 3.17.0)
116
115
  parallel (~> 1.10)
@@ -118,24 +117,25 @@ GEM
118
117
  rainbow (>= 2.2.2, < 4.0)
119
118
  regexp_parser (>= 1.8, < 3.0)
120
119
  rexml (>= 3.2.5, < 4.0)
121
- rubocop-ast (>= 1.28.1, < 2.0)
120
+ rubocop-ast (>= 1.30.0, < 2.0)
122
121
  ruby-progressbar (~> 1.7)
123
122
  unicode-display_width (>= 2.4.0, < 3.0)
124
- rubocop-ast (1.29.0)
123
+ rubocop-ast (1.30.0)
125
124
  parser (>= 3.2.1.0)
126
125
  rubocop-capybara (2.19.0)
127
126
  rubocop (~> 1.41)
128
127
  rubocop-factory_bot (2.24.0)
129
128
  rubocop (~> 1.33)
130
- rubocop-performance (1.19.1)
131
- rubocop (>= 1.7.0, < 2.0)
132
- rubocop-ast (>= 0.4.0)
133
- rubocop-rails (2.21.2)
129
+ rubocop-performance (1.20.1)
130
+ rubocop (>= 1.48.1, < 2.0)
131
+ rubocop-ast (>= 1.30.0, < 2.0)
132
+ rubocop-rails (2.23.1)
134
133
  activesupport (>= 4.2.0)
135
134
  rack (>= 1.1)
136
135
  rubocop (>= 1.33.0, < 2.0)
137
- rubocop-rspec (2.24.1)
138
- rubocop (~> 1.33)
136
+ rubocop-ast (>= 1.30.0, < 2.0)
137
+ rubocop-rspec (2.25.0)
138
+ rubocop (~> 1.40)
139
139
  rubocop-capybara (~> 2.17)
140
140
  rubocop-factory_bot (~> 2.22)
141
141
  ruby-progressbar (1.13.0)
@@ -148,7 +148,7 @@ GEM
148
148
  simplecov_json_formatter (~> 0.1)
149
149
  simplecov-html (0.12.3)
150
150
  simplecov_json_formatter (0.1.4)
151
- thor (1.2.2)
151
+ thor (1.3.0)
152
152
  tzinfo (2.0.6)
153
153
  concurrent-ruby (~> 1.0)
154
154
  unicode-display_width (2.5.0)
@@ -175,4 +175,4 @@ DEPENDENCIES
175
175
  simplecov
176
176
 
177
177
  BUNDLED WITH
178
- 2.4.18
178
+ 2.5.3
@@ -23,7 +23,7 @@ module ProformaXML
23
23
  if object.is_a? Hash
24
24
  object[name] = value
25
25
  else
26
- object.send("#{name}=", value)
26
+ object.send(:"#{name}=", value)
27
27
  end
28
28
  end
29
29
 
@@ -56,10 +56,10 @@ module ProformaXML
56
56
  end
57
57
 
58
58
  def add_test_configuration(test, test_node)
59
- test_configuration_node = test_node.xpath('xmlns:test-configuration')
59
+ test_configuration_node = test_node.xpath("#{@pro_ns}:test-configuration")
60
60
  test.files = test_files_from_test_configuration(test_configuration_node)
61
61
  test.configuration = extra_configuration_from_test_configuration(test_configuration_node)
62
- meta_data_node = test_node.xpath('xmlns:test-configuration').xpath('xmlns:test-meta-data')
62
+ meta_data_node = test_node.xpath("#{@pro_ns}:test-configuration").xpath("#{@pro_ns}:test-meta-data")
63
63
  test.meta_data = convert_xml_node_to_json(meta_data_node) if meta_data_node.present?
64
64
  end
65
65
 
@@ -75,28 +75,35 @@ module ProformaXML
75
75
  end
76
76
 
77
77
  def test_files_from_test_configuration(test_configuration_node)
78
- files_from_filerefs(test_configuration_node.search('filerefs'))
78
+ files_from_filerefs(test_configuration_node.xpath("#{@pro_ns}:filerefs"))
79
79
  end
80
80
 
81
81
  private
82
82
 
83
83
  def convert_xml_node_to_json(any_node)
84
84
  xml_snippet = Nokogiri::XML::DocumentFragment.new(Nokogiri::XML::Document.new, any_node)
85
- all_namespaces(any_node).each do |namespace|
85
+ all_namespaces_without_default(any_node).each do |namespace|
86
86
  xml_snippet.children.first.add_namespace_definition(namespace[:prefix], namespace[:href])
87
87
  end
88
- JSON.parse(Dachsfisch::XML2JSONConverter.perform(xml: xml_snippet.to_xml))
88
+ xml_without_custom_default_ns = xml_snippet.to_xml.gsub(%r{(</?)#{custom_default_namespace_prefix(any_node)}:}, '\1')
89
+ JSON.parse(Dachsfisch::XML2JSONConverter.perform(xml: xml_without_custom_default_ns))
89
90
  end
90
91
 
91
- def all_namespaces(node)
92
+ def all_namespaces_without_default(node)
92
93
  node.xpath('.|.//*').map(&:namespace).reject do |ns|
93
- ns.prefix.nil?
94
+ ns.prefix.nil? || ns.href.match?(/^urn:proforma:v\d.*$/)
94
95
  end.map {|ns| {prefix: ns.prefix, href: ns.href} }.uniq
95
96
  end
96
97
 
98
+ def custom_default_namespace_prefix(node)
99
+ node.xpath('.|.//*').map(&:namespace).filter do |ns|
100
+ ns.href.match?(/^urn:proforma:v\d.*$/)
101
+ end.map(&:prefix).first
102
+ end
103
+
97
104
  def value_from_node(name, node, attribute)
98
105
  xml_name = name.is_a?(Array) ? name[0] : name
99
- attribute ? node.attribute(xml_name)&.value : node.xpath("xmlns:#{xml_name}").text
106
+ attribute ? node.attribute(xml_name)&.value : node.xpath("#{@pro_ns}:#{xml_name}").text
100
107
  end
101
108
 
102
109
  def content_from_file_tag(file_tag, binary)
@@ -18,12 +18,21 @@ module ProformaXML
18
18
  @task = Task.new
19
19
  end
20
20
 
21
+ def proforma_namespace
22
+ namespace_regex = /^urn:proforma:v\d.*$/
23
+ namespaces = @doc.namespaces.filter do |_, href|
24
+ href.match? namespace_regex
25
+ end
26
+ namespaces.first.first.gsub('xmlns:', '')
27
+ end
28
+
21
29
  def perform
22
30
  errors = validate
23
31
 
24
32
  raise PreImportValidationError.new(errors) if errors.any?
25
33
 
26
- @task_node = @doc.xpath('/xmlns:task')
34
+ @pro_ns = proforma_namespace
35
+ @task_node = @doc.xpath("/#{@pro_ns}:task")
27
36
 
28
37
  set_data
29
38
  @task
@@ -37,11 +46,17 @@ module ProformaXML
37
46
  end
38
47
  end
39
48
 
49
+ def remove_referenced_files
50
+ referenced_files = (@task.tests.map(&:files) + @task.model_solutions.map(&:files)).flatten
51
+ @task.files.reject! {|f| referenced_files.include? f }
52
+ end
53
+
40
54
  def set_data
41
55
  set_base_data
42
56
  set_files
43
57
  set_model_solutions
44
58
  set_tests
59
+ remove_referenced_files
45
60
  set_meta_data
46
61
  set_extra_data
47
62
  end
@@ -57,44 +72,44 @@ module ProformaXML
57
72
  end
58
73
 
59
74
  def set_proglang
60
- return if @task_node.xpath('xmlns:proglang').text.blank?
75
+ return if @task_node.xpath("#{@pro_ns}:proglang").text.blank?
61
76
 
62
- @task.proglang = {name: @task_node.xpath('xmlns:proglang').text,
63
- version: @task_node.xpath('xmlns:proglang').attribute('version').value.presence}.compact
77
+ @task.proglang = {name: @task_node.xpath("#{@pro_ns}:proglang").text,
78
+ version: @task_node.xpath("#{@pro_ns}:proglang").attribute('version').value.presence}.compact
64
79
  end
65
80
 
66
81
  def set_files
67
- @task_node.search('files//file').each {|file_node| add_file file_node }
82
+ @task_node.xpath("#{@pro_ns}:files//#{@pro_ns}:file").each {|file_node| add_file file_node }
68
83
  end
69
84
 
70
85
  def set_tests
71
- @task_node.search('tests//test').each {|test_node| add_test test_node }
86
+ @task_node.xpath("#{@pro_ns}:tests//#{@pro_ns}:test").each {|test_node| add_test test_node }
72
87
  end
73
88
 
74
89
  def set_model_solutions
75
- @task_node.search('model-solutions//model-solution').each do |model_solution_node|
90
+ @task_node.xpath("#{@pro_ns}:model-solutions//#{@pro_ns}:model-solution").each do |model_solution_node|
76
91
  add_model_solution model_solution_node
77
92
  end
78
93
  end
79
94
 
80
95
  def set_meta_data
81
- meta_data_node = @task_node.xpath('xmlns:meta-data').first
96
+ meta_data_node = @task_node.xpath("#{@pro_ns}:meta-data").first
82
97
  @task.meta_data = convert_xml_node_to_json(meta_data_node) if meta_data_node.text.present?
83
98
  end
84
99
 
85
100
  def set_extra_data
86
- submission_restrictions_node = @task_node.xpath('xmlns:submission-restrictions').first
101
+ submission_restrictions_node = @task_node.xpath("#{@pro_ns}:submission-restrictions").first
87
102
  @task.submission_restrictions = convert_xml_node_to_json(submission_restrictions_node) unless submission_restrictions_node.nil?
88
- external_resources_node = @task_node.xpath('xmlns:external-resources').first
103
+ external_resources_node = @task_node.xpath("#{@pro_ns}:external-resources").first
89
104
  @task.external_resources = convert_xml_node_to_json(external_resources_node) unless external_resources_node.nil?
90
- grading_hints_node = @task_node.xpath('xmlns:grading-hints').first
105
+ grading_hints_node = @task_node.xpath("#{@pro_ns}:grading-hints").first
91
106
  @task.grading_hints = convert_xml_node_to_json(grading_hints_node) unless grading_hints_node.nil?
92
107
  end
93
108
 
94
109
  def add_model_solution(model_solution_node)
95
110
  model_solution = ModelSolution.new
96
111
  model_solution.id = model_solution_node.attributes['id'].value
97
- model_solution.files = files_from_filerefs(model_solution_node.search('filerefs'))
112
+ model_solution.files = files_from_filerefs(model_solution_node.xpath("#{@pro_ns}:filerefs"))
98
113
  set_value_from_xml(object: model_solution, node: model_solution_node, name: 'description')
99
114
  set_value_from_xml(object: model_solution, node: model_solution_node, name: 'internal-description')
100
115
  @task.model_solutions << model_solution unless model_solution.files.first&.id == 'ms-placeholder-file'
@@ -125,9 +140,9 @@ module ProformaXML
125
140
 
126
141
  def files_from_filerefs(filerefs_node)
127
142
  [].tap do |files|
128
- filerefs_node.search('fileref').each do |fileref_node|
143
+ filerefs_node.xpath("#{@pro_ns}:fileref").each do |fileref_node|
129
144
  fileref = fileref_node.attributes['refid'].value
130
- files << @task.files.delete(@task.files.detect {|file| file.id == fileref })
145
+ files << @task.files.detect {|file| file.id == fileref }
131
146
  end
132
147
  end
133
148
  end
@@ -14,7 +14,14 @@ module ProformaXML
14
14
  private
15
15
 
16
16
  def doc_schema_version
17
- @doc_schema_version ||= /^urn:proforma:v(.*)$/.match(@doc.namespaces['xmlns'])&.captures&.dig(0)
17
+ namespace_regex = /^urn:proforma:v(\d.*)$/
18
+ potential_namespaces = @doc.namespaces.filter do |_, href|
19
+ href.match? namespace_regex
20
+ end
21
+ return nil unless potential_namespaces.length == 1
22
+
23
+ @pro_ns = potential_namespaces.first[0].gsub('xmlns:', '')
24
+ @doc_schema_version ||= namespace_regex.match(potential_namespaces.first[1])&.captures&.dig(0)
18
25
  end
19
26
 
20
27
  def node_as_doc_with_namespace(config_node)
@@ -38,7 +45,7 @@ module ProformaXML
38
45
  end
39
46
 
40
47
  def validate_test_configuration
41
- @doc.xpath('/xmlns:task/xmlns:tests/xmlns:test/xmlns:test-configuration').flat_map do |test_config|
48
+ @doc.xpath("/#{@pro_ns}:task/#{@pro_ns}:tests/#{@pro_ns}:test/#{@pro_ns}:test-configuration").flat_map do |test_config|
42
49
  test_config.children.flat_map do |config_node|
43
50
  next [] unless config_node.namespace&.href&.start_with?('urn:proforma:tests:')
44
51
  next [] unless TEST_TYPE_SCHEMA_NAMES.include? config_node.name
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ProformaXML
4
- VERSION = '1.2.0'
4
+ VERSION = '1.3.0'
5
5
  end
data/proformaxml.gemspec CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = 'https://github.com/openHPI/proformaxml'
14
14
  spec.license = 'MIT'
15
15
 
16
- spec.required_ruby_version = '>= 3.2'
16
+ spec.required_ruby_version = '>= 3.3'
17
17
 
18
18
  # Specify which files should be added to the gem when it is released.
19
19
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: proformaxml
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karol
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-25 00:00:00.000000000 Z
11
+ date: 2024-04-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -160,14 +160,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
160
160
  requirements:
161
161
  - - ">="
162
162
  - !ruby/object:Gem::Version
163
- version: '3.2'
163
+ version: '3.3'
164
164
  required_rubygems_version: !ruby/object:Gem::Requirement
165
165
  requirements:
166
166
  - - ">="
167
167
  - !ruby/object:Gem::Version
168
168
  version: '0'
169
169
  requirements: []
170
- rubygems_version: 3.4.1
170
+ rubygems_version: 3.5.3
171
171
  signing_key:
172
172
  specification_version: 4
173
173
  summary: Implements parts of ProFormA-XML specification