proformaxml 0.10.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2230a680b6a36b22867d4c9749199e5ab0e601567998e343e3281a838867f6c7
4
- data.tar.gz: 9e8486a4ed110915ff0e9ce4b6e4cf87df3ad02c8c0c94c02824ddd8696a56fc
3
+ metadata.gz: 81e1724c3c9498d52025b18b5f3e2830fa10c499bcc9a064470f265d6ed9ba34
4
+ data.tar.gz: 4b7499f6e605ba8dae8ad23e149a06e7e78fa08f91a14f3e8803e70140b02cdc
5
5
  SHA512:
6
- metadata.gz: 20e9ee57cc1071bf2b8612f3397aeed1a98648f0fc363ddb8e3b22251c77e265208b6fbce75c9fe19cafd5a454fcf97d5f8dd90312a7758a2f86c673db9596ea
7
- data.tar.gz: 1c9d253c304209ba0026b766585d851d99e4ea3a626c402d92feb78a245b9ffc7633130ccea1bfe7916315a9118eff54b092b0252c8b88487fccf0547aa70313
6
+ metadata.gz: c47047c96d5fb1c23233c67bd165a6b088e643bc9b6032c8107afd1e32d8d3cb9c4d2342661bd0b5b2b9da38fee368a058dc2fdfa2aabd34889f49c3e9817c21
7
+ data.tar.gz: 18e38170e845ad6e148ce0de1f621e57c3b360a19c7e3a875d8be90e1dfaf94fc085aacdd18ab16d6a587116261426e1f6de6939a351d5fdb0a683e218c7ed1d
@@ -0,0 +1,5 @@
1
+ # factory bot cop settings
2
+
3
+ # We need to define own IDs, since we do not store objects in a database with ActiveRecord.
4
+ FactoryBot/IdSequence:
5
+ Enabled: false
data/.rubocop/rspec.yml CHANGED
@@ -25,3 +25,11 @@ RSpec/NestedGroups:
25
25
 
26
26
  RSpec/IndexedLet:
27
27
  Max: 2
28
+
29
+ RSpec/FilePath:
30
+ CustomTransform:
31
+ ProformaXML: proformaxml
32
+
33
+ RSpec/SpecFilePathFormat:
34
+ CustomTransform:
35
+ ProformaXML: proformaxml
data/.rubocop.yml CHANGED
@@ -5,6 +5,7 @@ require:
5
5
  - rubocop-rspec
6
6
 
7
7
  inherit_from:
8
+ - .rubocop/factory-bot.yml
8
9
  - .rubocop/layout.yml
9
10
  - .rubocop/lint.yml
10
11
  - .rubocop/metrics.yml
@@ -24,7 +25,3 @@ AllCops:
24
25
  - 'tmp/**/*'
25
26
  - 'out/**/*'
26
27
  - 'coverage/**/*'
27
-
28
- RSpec/FilePath:
29
- CustomTransform:
30
- ProformaXML: proformaxml
data/Gemfile CHANGED
@@ -16,7 +16,6 @@ gem 'rspec'
16
16
  gem 'rspec-collection_matchers'
17
17
  gem 'rspec-github'
18
18
  gem 'rubocop'
19
- gem 'rubocop-factory_bot'
20
19
  gem 'rubocop-performance'
21
20
  gem 'rubocop-rails'
22
21
  gem 'rubocop-rspec'
data/Gemfile.lock CHANGED
@@ -1,19 +1,19 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- proformaxml (0.10.0)
4
+ proformaxml (1.1.0)
5
5
  activemodel (>= 5.2.3, < 8.0.0)
6
6
  activesupport (>= 5.2.3, < 8.0.0)
7
- dachsfisch (>= 0.1.0, < 1.0.0)
7
+ dachsfisch (>= 0.2.0, < 1.0.0)
8
8
  nokogiri (>= 1.10.2, < 2.0.0)
9
9
  rubyzip (>= 1.2.2, < 3.0.0)
10
10
 
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- activemodel (7.0.7.2)
15
- activesupport (= 7.0.7.2)
16
- activesupport (7.0.7.2)
14
+ activemodel (7.0.8)
15
+ activesupport (= 7.0.8)
16
+ activesupport (7.0.8)
17
17
  concurrent-ruby (~> 1.0, >= 1.0.2)
18
18
  i18n (>= 1.6, < 2)
19
19
  minitest (>= 5.1)
@@ -23,15 +23,15 @@ GEM
23
23
  byebug (11.1.3)
24
24
  coderay (1.1.3)
25
25
  concurrent-ruby (1.2.2)
26
- dachsfisch (0.1.0)
26
+ dachsfisch (0.2.0)
27
27
  nokogiri (>= 1.14.1, < 2.0.0)
28
28
  diff-lcs (1.5.0)
29
29
  docile (1.4.0)
30
- factory_bot (6.2.1)
30
+ factory_bot (6.3.0)
31
31
  activesupport (>= 5.0.0)
32
- ffi (1.15.5)
32
+ ffi (1.16.1)
33
33
  formatador (1.1.0)
34
- guard (2.18.0)
34
+ guard (2.18.1)
35
35
  formatador (>= 0.2.4)
36
36
  listen (>= 2.7, < 4.0)
37
37
  lumberjack (>= 1.0.12, < 2.0)
@@ -55,7 +55,7 @@ GEM
55
55
  lumberjack (1.2.9)
56
56
  method_source (1.0.0)
57
57
  mini_portile2 (2.8.4)
58
- minitest (5.19.0)
58
+ minitest (5.20.0)
59
59
  nenv (0.3.0)
60
60
  nokogiri (1.15.4)
61
61
  mini_portile2 (~> 2.8.2)
@@ -86,7 +86,7 @@ GEM
86
86
  rspec-core (~> 3.12.0)
87
87
  rspec-expectations (~> 3.12.0)
88
88
  rspec-mocks (~> 3.12.0)
89
- rspec-collection_matchers (1.2.0)
89
+ rspec-collection_matchers (1.2.1)
90
90
  rspec-expectations (>= 2.99.0.beta1)
91
91
  rspec-core (3.12.2)
92
92
  rspec-support (~> 3.12.0)
@@ -99,7 +99,7 @@ GEM
99
99
  diff-lcs (>= 1.2.0, < 2.0)
100
100
  rspec-support (~> 3.12.0)
101
101
  rspec-support (3.12.1)
102
- rubocop (1.56.1)
102
+ rubocop (1.56.4)
103
103
  base64 (~> 0.1.1)
104
104
  json (~> 2.3)
105
105
  language_server-protocol (>= 3.17.0)
@@ -113,18 +113,18 @@ GEM
113
113
  unicode-display_width (>= 2.4.0, < 3.0)
114
114
  rubocop-ast (1.29.0)
115
115
  parser (>= 3.2.1.0)
116
- rubocop-capybara (2.18.0)
116
+ rubocop-capybara (2.19.0)
117
117
  rubocop (~> 1.41)
118
- rubocop-factory_bot (2.23.1)
118
+ rubocop-factory_bot (2.24.0)
119
119
  rubocop (~> 1.33)
120
- rubocop-performance (1.19.0)
120
+ rubocop-performance (1.19.1)
121
121
  rubocop (>= 1.7.0, < 2.0)
122
122
  rubocop-ast (>= 0.4.0)
123
- rubocop-rails (2.20.2)
123
+ rubocop-rails (2.21.2)
124
124
  activesupport (>= 4.2.0)
125
125
  rack (>= 1.1)
126
126
  rubocop (>= 1.33.0, < 2.0)
127
- rubocop-rspec (2.23.2)
127
+ rubocop-rspec (2.24.1)
128
128
  rubocop (~> 1.33)
129
129
  rubocop-capybara (~> 2.17)
130
130
  rubocop-factory_bot (~> 2.22)
@@ -140,7 +140,7 @@ GEM
140
140
  thor (1.2.2)
141
141
  tzinfo (2.0.6)
142
142
  concurrent-ruby (~> 1.0)
143
- unicode-display_width (2.4.2)
143
+ unicode-display_width (2.5.0)
144
144
 
145
145
  PLATFORMS
146
146
  ruby
@@ -158,7 +158,6 @@ DEPENDENCIES
158
158
  rspec-collection_matchers
159
159
  rspec-github
160
160
  rubocop
161
- rubocop-factory_bot
162
161
  rubocop-performance
163
162
  rubocop-rails
164
163
  rubocop-rspec
@@ -26,54 +26,32 @@ module ProformaXML
26
26
  def add_test_configuration(xml, test)
27
27
  xml.send(:'test-configuration') do
28
28
  add_filerefs(xml, test) if test.files
29
- add_configuration(xml, test.configuration) unless test.configuration.nil?
30
- if test.meta_data
31
- xml.send(:'test-meta-data') do
32
- meta_data(xml, test.meta_data)
33
- end
34
- end
29
+ add_dachsfisch_node(xml, test.configuration)
30
+ add_dachsfisch_node(xml, test.meta_data)
35
31
  end
36
32
  end
37
33
 
38
- def inner_meta_data(xml, namespace, data)
39
- data.each do |key, value|
40
- case value.class.name
41
- when 'Hash'
42
- # underscore is used to disambiguate tag names from ruby methods
43
- xml[namespace].send("#{key}_") do |meta_data_xml|
44
- inner_meta_data(meta_data_xml, namespace, value)
45
- end
46
- else
47
- xml[namespace].send("#{key}_", value)
48
- end
49
- end
50
- end
51
-
52
- def meta_data(xml, meta_data)
53
- meta_data.each do |namespace, data|
54
- inner_meta_data(xml, namespace, data)
55
- end
56
- end
57
-
58
- def add_configuration(xml, configuration)
59
- xml_snippet = Dachsfisch::JSON2XMLConverter.perform(json: configuration.to_json)
60
- configuration.flat_map {|_, val| val['@xmlns'].to_a }.uniq.each do |namespace|
61
- xml.doc.root.add_namespace(namespace[0], namespace[1])
34
+ def add_dachsfisch_node(xml, dachsfisch_node, node_name_fallback = nil)
35
+ if dachsfisch_node.blank?
36
+ xml.send(node_name_fallback, '') if node_name_fallback.present?
37
+ return
62
38
  end
39
+ xml_snippet = Dachsfisch::JSON2XMLConverter.perform(json: dachsfisch_node.to_json)
40
+ add_namespaces_for_dachsfisch_node(dachsfisch_node, xml)
63
41
 
64
42
  xml << xml_snippet
65
43
  end
66
44
 
67
- def add_namespaces_to_header(header, custom_namespaces)
68
- custom_namespaces.each do |namespace|
69
- header["xmlns:#{namespace[:prefix]}"] = namespace[:uri]
70
- end
71
- end
72
-
73
45
  def add_parent_uuid_and_lang_to_header(header)
74
46
  header['lang'] = @task.language if @task.language.present?
75
47
  header['parent-uuid'] = @task.parent_uuid if @task.parent_uuid.present?
76
48
  end
49
+
50
+ def add_namespaces_for_dachsfisch_node(dachsfisch_node, xml)
51
+ dachsfisch_node.flat_map {|_, val| val['@xmlns'].to_a }.uniq.each do |namespace|
52
+ xml.doc.root.add_namespace(namespace[0], namespace[1]) unless namespace[0] == '$'
53
+ end
54
+ end
77
55
  end
78
56
  end
79
57
  end
@@ -60,7 +60,7 @@ module ProformaXML
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
62
  meta_data_node = test_node.xpath('xmlns:test-configuration').xpath('xmlns:test-meta-data')
63
- test.meta_data = meta_data(meta_data_node, use_namespace: true) if meta_data_node.present?
63
+ test.meta_data = convert_xml_node_to_json(meta_data_node) if meta_data_node.present?
64
64
  end
65
65
 
66
66
  def extra_configuration_from_test_configuration(test_configuration_node)
@@ -78,29 +78,22 @@ module ProformaXML
78
78
  files_from_filerefs(test_configuration_node.search('filerefs'))
79
79
  end
80
80
 
81
- def meta_data(any_data_node, use_namespace: false)
82
- # use_namespace forces the use of the namespace as hash key - it should only be used at the entry of the recursion
83
- {}.tap do |any_data|
84
- any_data_node.children.each do |node|
85
- key = (use_namespace ? node.namespace.prefix : any_data_node.name).to_sym
86
- any_data[key] = if node.node_type == Nokogiri::XML::Node::TEXT_NODE
87
- node.text
88
- else
89
- # preserve any existing data in the nested hash
90
- (any_data[key] || {}).merge meta_data(node)
91
- end
92
- end
93
- end
94
- end
95
-
96
81
  private
97
82
 
98
83
  def convert_xml_node_to_json(any_node)
99
84
  xml_snippet = Nokogiri::XML::DocumentFragment.new(Nokogiri::XML::Document.new, any_node)
100
- xml_snippet.children.first.add_namespace_definition(any_node.namespace.prefix, any_node.namespace.href)
85
+ all_namespaces(any_node).each do |namespace|
86
+ xml_snippet.children.first.add_namespace_definition(namespace[:prefix], namespace[:href])
87
+ end
101
88
  JSON.parse(Dachsfisch::XML2JSONConverter.perform(xml: xml_snippet.to_xml))
102
89
  end
103
90
 
91
+ def all_namespaces(node)
92
+ node.xpath('.|.//*').map(&:namespace).reject do |ns|
93
+ ns.prefix.nil?
94
+ end.map {|ns| {prefix: ns.prefix, href: ns.href} }.uniq
95
+ end
96
+
104
97
  def value_from_node(name, node, attribute)
105
98
  xml_name = name.is_a?(Array) ? name[0] : name
106
99
  attribute ? node.attribute(xml_name)&.value : node.xpath("xmlns:#{xml_name}").text
@@ -8,8 +8,8 @@ require 'proformaxml/errors'
8
8
 
9
9
  module ProformaXML
10
10
  class Task < Base
11
- attr_accessor :title, :description, :internal_description, :proglang, :uuid, :parent_uuid,
12
- :language, :model_solutions, :files, :tests, :meta_data
11
+ attr_accessor :title, :description, :internal_description, :proglang, :uuid, :parent_uuid, :language,
12
+ :model_solutions, :files, :tests, :meta_data, :submission_restrictions, :external_resources, :grading_hints
13
13
 
14
14
  def initialize(attributes = {})
15
15
  super
@@ -6,10 +6,9 @@ module ProformaXML
6
6
  class Exporter
7
7
  include ProformaXML::Helpers::ExportHelpers
8
8
 
9
- def initialize(task:, custom_namespaces: [], version: nil)
9
+ def initialize(task:, version: nil)
10
10
  @files = {}
11
11
  @task = task
12
- @custom_namespaces = custom_namespaces
13
12
  @version = version || SCHEMA_VERSIONS.first
14
13
  add_placeholders if @version == '2.0'
15
14
  end
@@ -22,9 +21,9 @@ module ProformaXML
22
21
  doc = Nokogiri::XML(xmldoc)
23
22
  errors = validate(doc)
24
23
 
24
+ # File.binwrite('../testfile.zip', write_to_zip(xmldoc).string)
25
25
  raise PostGenerateValidationError.new(errors) if errors.any?
26
26
 
27
- # File.open('../testfile.zip', 'wb') { |file| file.write(write_to_zip(xmldoc).string) }
28
27
  write_to_zip(xmldoc)
29
28
  end
30
29
 
@@ -38,7 +37,7 @@ module ProformaXML
38
37
  xml.proglang({version: @task.proglang&.dig(:version)}, @task.proglang&.dig(:name))
39
38
 
40
39
  add_objects_to_xml(xml)
41
- add_meta_data(xml)
40
+ add_dachsfisch_node(xml, @task.meta_data, 'meta-data')
42
41
  end
43
42
  end
44
43
 
@@ -46,14 +45,13 @@ module ProformaXML
46
45
  xml.send(:'internal-description', internal_description) if internal_description.present?
47
46
  end
48
47
 
49
- def add_meta_data(xml)
50
- xml.send(:'meta-data') { meta_data(xml, @task.meta_data) }
51
- end
52
-
53
48
  def add_objects_to_xml(xml)
49
+ add_dachsfisch_node(xml, @task.submission_restrictions)
54
50
  xml.files { files(xml) }
51
+ add_dachsfisch_node(xml, @task.external_resources)
55
52
  xml.send(:'model-solutions') { model_solutions(xml) } if @task.model_solutions.any? || @version == '2.0'
56
53
  xml.tests { tests(xml) }
54
+ add_dachsfisch_node(xml, @task.grading_hints)
57
55
  end
58
56
 
59
57
  def files(xml)
@@ -114,7 +112,6 @@ module ProformaXML
114
112
  'xmlns' => "urn:proforma:v#{@version}",
115
113
  'uuid' => @task.uuid,
116
114
  }.tap do |header|
117
- add_namespaces_to_header(header, @custom_namespaces)
118
115
  add_parent_uuid_and_lang_to_header(header)
119
116
  end
120
117
  end
@@ -26,7 +26,7 @@ module ProformaXML
26
26
  @task_node = @doc.xpath('/xmlns:task')
27
27
 
28
28
  set_data
29
- {task: @task, custom_namespaces: @custom_namespaces}
29
+ @task
30
30
  end
31
31
 
32
32
  private
@@ -38,16 +38,12 @@ module ProformaXML
38
38
  end
39
39
 
40
40
  def set_data
41
- set_namespaces
42
41
  set_base_data
43
42
  set_files
44
43
  set_model_solutions
45
44
  set_tests
46
45
  set_meta_data
47
- end
48
-
49
- def set_namespaces
50
- @custom_namespaces = @doc.namespaces.except('xmlns').map {|k, v| {prefix: k[6..], uri: v} }
46
+ set_extra_data
51
47
  end
52
48
 
53
49
  def set_base_data
@@ -82,8 +78,17 @@ module ProformaXML
82
78
  end
83
79
 
84
80
  def set_meta_data
85
- meta_data_node = @task_node.xpath('xmlns:meta-data')
86
- @task.meta_data = meta_data(meta_data_node, use_namespace: true) if meta_data_node.text.present?
81
+ meta_data_node = @task_node.xpath('xmlns:meta-data').first
82
+ @task.meta_data = convert_xml_node_to_json(meta_data_node) if meta_data_node.text.present?
83
+ end
84
+
85
+ def set_extra_data
86
+ submission_restrictions_node = @task_node.xpath('xmlns:submission-restrictions').first
87
+ @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
89
+ @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
91
+ @task.grading_hints = convert_xml_node_to_json(grading_hints_node) unless grading_hints_node.nil?
87
92
  end
88
93
 
89
94
  def add_model_solution(model_solution_node)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ProformaXML
4
- VERSION = '0.10.0'
4
+ VERSION = '1.1.0'
5
5
  end
data/proformaxml.gemspec CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
29
29
 
30
30
  spec.add_dependency 'activemodel', '>= 5.2.3', '< 8.0.0'
31
31
  spec.add_dependency 'activesupport', '>= 5.2.3', '< 8.0.0'
32
- spec.add_dependency 'dachsfisch', '>= 0.1.0', '< 1.0.0'
32
+ spec.add_dependency 'dachsfisch', '>= 0.2.0', '< 1.0.0'
33
33
  spec.add_dependency 'nokogiri', '>= 1.10.2', '< 2.0.0'
34
34
  spec.add_dependency 'rubyzip', '>= 1.2.2', '< 3.0.0'
35
35
 
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: 0.10.0
4
+ version: 1.1.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-08-22 00:00:00.000000000 Z
11
+ date: 2023-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -56,7 +56,7 @@ dependencies:
56
56
  requirements:
57
57
  - - ">="
58
58
  - !ruby/object:Gem::Version
59
- version: 0.1.0
59
+ version: 0.2.0
60
60
  - - "<"
61
61
  - !ruby/object:Gem::Version
62
62
  version: 1.0.0
@@ -66,7 +66,7 @@ dependencies:
66
66
  requirements:
67
67
  - - ">="
68
68
  - !ruby/object:Gem::Version
69
- version: 0.1.0
69
+ version: 0.2.0
70
70
  - - "<"
71
71
  - !ruby/object:Gem::Version
72
72
  version: 1.0.0
@@ -119,6 +119,7 @@ extra_rdoc_files: []
119
119
  files:
120
120
  - ".rspec"
121
121
  - ".rubocop.yml"
122
+ - ".rubocop/factory-bot.yml"
122
123
  - ".rubocop/layout.yml"
123
124
  - ".rubocop/lint.yml"
124
125
  - ".rubocop/metrics.yml"
@@ -172,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
172
173
  - !ruby/object:Gem::Version
173
174
  version: '0'
174
175
  requirements: []
175
- rubygems_version: 3.4.19
176
+ rubygems_version: 3.4.6
176
177
  signing_key:
177
178
  specification_version: 4
178
179
  summary: Implements parts of ProFormA-XML specification