swissmedic-diff 0.3.0 → 0.3.1

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: 148fd8071ce6cb4e6d8800719cf00a9389533d78b44639e3e6d8abdf63e748ec
4
- data.tar.gz: 9f898594652b70299dd2813632cfe5c802cc36fa8d5281af1bf53f0e264ba368
3
+ metadata.gz: dbedd2453003bfa00e428d41445471400b23c016a04cc19708dd13e82a390192
4
+ data.tar.gz: 3df6a9a5b8f38e6f0016c35e4c8eb8b6b3aefc3b5d01cbda1ff86c2fca451ce4
5
5
  SHA512:
6
- metadata.gz: 103e81c93f7df059a2985f7840c5092441438a2c57d8b360470aa6e242f17937170ae91a20ec4aa90c1727c5ee279bc84832047b1c1c185482d5a207bc5e497b
7
- data.tar.gz: f9d4ceedc50676eaa4ccb3bbab86d11e70db961ec7f879b6d39b9aa93bd54cf479bc7860f75d2bf239d2ca7444ae3a358b506f53985a574ad8cf6199da4aa0a7
6
+ metadata.gz: 4f0c588ba8a0949c18015b582a37084406d6b79394fd2bd6e7452c1f79199232594f637d569f018da135e4500ff4fb1be5af563887f9a38a29807dc9e5722b08
7
+ data.tar.gz: 4c07343f38c2322d6a872af07855b5006e310f3e3dc0d6c4a1ed3e62544b344044260c6b8af40160c029dc15e2974d165e7eaffcd3957281e4f6ff640ea1a6e2
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- swissmedic-diff (0.3.0)
4
+ swissmedic-diff (0.3.1)
5
5
  logger
6
6
  nokogiri
7
7
  ostruct
@@ -14,62 +14,52 @@ GEM
14
14
  ansi (1.5.0)
15
15
  ast (2.4.3)
16
16
  builder (3.3.0)
17
- byebug (11.1.3)
18
- coderay (1.1.3)
19
- date (3.4.1)
20
- debug (1.11.0)
17
+ date (3.5.1)
18
+ debug (1.11.1)
21
19
  irb (~> 1.10)
22
20
  reline (>= 0.3.8)
23
- erb (5.0.1)
24
- io-console (0.8.0)
25
- irb (1.15.2)
21
+ erb (6.0.1)
22
+ io-console (0.8.2)
23
+ irb (1.16.0)
26
24
  pp (>= 0.6.0)
27
25
  rdoc (>= 4.0.0)
28
26
  reline (>= 0.4.2)
29
- json (2.12.2)
27
+ json (2.18.0)
30
28
  language_server-protocol (3.17.0.5)
31
29
  lint_roller (1.1.0)
32
- logger (1.6.4)
33
- method_source (1.1.0)
34
- minitest (5.25.4)
30
+ logger (1.7.0)
31
+ minitest (6.0.1)
32
+ prism (~> 1.5)
35
33
  minitest-reporters (1.7.1)
36
34
  ansi
37
35
  builder
38
36
  minitest (>= 5.0)
39
37
  ruby-progressbar
40
- nokogiri (1.18.1-x86_64-linux-gnu)
38
+ nokogiri (1.19.0-x86_64-linux-gnu)
41
39
  racc (~> 1.4)
42
- ostruct (0.6.1)
40
+ ostruct (0.6.3)
43
41
  parallel (1.27.0)
44
- parser (3.3.8.0)
42
+ parser (3.3.10.0)
45
43
  ast (~> 2.4.1)
46
44
  racc
47
- pp (0.6.2)
45
+ pp (0.6.3)
48
46
  prettyprint
49
47
  prettyprint (0.2.0)
50
- prism (1.4.0)
51
- pry (0.14.2)
52
- coderay (~> 1.1)
53
- method_source (~> 1.0)
54
- pry-byebug (3.10.1)
55
- byebug (~> 11.0)
56
- pry (>= 0.13, < 0.15)
57
- pry-doc (1.5.0)
58
- pry (~> 0.11)
59
- yard (~> 0.9.11)
60
- psych (5.2.6)
48
+ prism (1.7.0)
49
+ psych (5.3.1)
61
50
  date
62
51
  stringio
63
52
  racc (1.8.1)
64
53
  rainbow (3.1.1)
65
- rake (13.2.1)
66
- rdoc (6.14.2)
54
+ rake (13.3.1)
55
+ rdoc (7.0.3)
67
56
  erb
68
57
  psych (>= 4.0.0)
69
- regexp_parser (2.10.0)
70
- reline (0.6.1)
58
+ tsort
59
+ regexp_parser (2.11.3)
60
+ reline (0.6.3)
71
61
  io-console (~> 0.5)
72
- rubocop (1.75.8)
62
+ rubocop (1.81.7)
73
63
  json (~> 2.3)
74
64
  language_server-protocol (~> 3.17.0.2)
75
65
  lint_roller (~> 1.1.0)
@@ -77,38 +67,38 @@ GEM
77
67
  parser (>= 3.3.0.2)
78
68
  rainbow (>= 2.2.2, < 4.0)
79
69
  regexp_parser (>= 2.9.3, < 3.0)
80
- rubocop-ast (>= 1.44.0, < 2.0)
70
+ rubocop-ast (>= 1.47.1, < 2.0)
81
71
  ruby-progressbar (~> 1.7)
82
72
  unicode-display_width (>= 2.4.0, < 4.0)
83
- rubocop-ast (1.45.1)
73
+ rubocop-ast (1.49.0)
84
74
  parser (>= 3.3.7.2)
85
- prism (~> 1.4)
86
- rubocop-performance (1.25.0)
75
+ prism (~> 1.7)
76
+ rubocop-performance (1.26.1)
87
77
  lint_roller (~> 1.1)
88
78
  rubocop (>= 1.75.0, < 2.0)
89
- rubocop-ast (>= 1.38.0, < 2.0)
79
+ rubocop-ast (>= 1.47.1, < 2.0)
90
80
  ruby-progressbar (1.13.0)
91
- rubyzip (2.4.1)
81
+ rubyzip (3.2.2)
92
82
  simple_xlsx_reader (5.1.0)
93
83
  nokogiri
94
84
  rubyzip
95
- standard (1.50.0)
85
+ standard (1.52.0)
96
86
  language_server-protocol (~> 3.17.0.2)
97
87
  lint_roller (~> 1.0)
98
- rubocop (~> 1.75.5)
88
+ rubocop (~> 1.81.7)
99
89
  standard-custom (~> 1.0.0)
100
90
  standard-performance (~> 1.8)
101
91
  standard-custom (1.0.2)
102
92
  lint_roller (~> 1.0)
103
93
  rubocop (~> 1.50)
104
- standard-performance (1.8.0)
94
+ standard-performance (1.9.0)
105
95
  lint_roller (~> 1.1)
106
- rubocop-performance (~> 1.25.0)
107
- stringio (3.1.7)
108
- unicode-display_width (3.1.4)
109
- unicode-emoji (~> 4.0, >= 4.0.4)
110
- unicode-emoji (4.0.4)
111
- yard (0.9.37)
96
+ rubocop-performance (~> 1.26.0)
97
+ stringio (3.2.0)
98
+ tsort (0.2.0)
99
+ unicode-display_width (3.2.0)
100
+ unicode-emoji (~> 4.1)
101
+ unicode-emoji (4.2.0)
112
102
 
113
103
  PLATFORMS
114
104
  x86_64-linux
@@ -117,8 +107,6 @@ DEPENDENCIES
117
107
  debug
118
108
  minitest
119
109
  minitest-reporters
120
- pry-byebug
121
- pry-doc
122
110
  rake
123
111
  standard
124
112
  swissmedic-diff!
data/History.md CHANGED
@@ -1,3 +1,11 @@
1
+ # 0.3.1 / 09.01.2026
2
+ * Ruby 4.0 to tests
3
+ * Added stat method to show the result of the diff
4
+ * Fixes for running bundle exec ruby bin/swissmedic-diff
5
+ * Use standardrb to format the code
6
+ * Removed unused constant GALFORM_P
7
+ * Requires at least Ruby 2.6
8
+
1
9
  # 0.3.0 / 05.07.2025
2
10
 
3
11
  * Use simple_xlsx_reader insted of RubyXL to speed up comparision
Binary file
Binary file
data/Rakefile CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  require "rubygems"
4
4
  require "bundler/gem_tasks"
5
-
5
+ require "rake/testtask"
6
6
  require "rake/clean"
7
+
7
8
  CLEAN.include FileList["*.log"]
9
+
10
+ Rake::TestTask.new do |t|
11
+ t.libs << "test"
12
+ t.test_files = FileList["test/test_*.rb"]
13
+ end
@@ -75,7 +75,6 @@ class SwissmedicDiff
75
75
  production_science: "Heilmittelcode",
76
76
  atc_class: "ATC-Code"
77
77
  }
78
- GALFORM_P = %r{excipiens\s+(ad|pro)\s+(?<galform>((?!\bpro\b)[^.])+)}
79
78
  DATE_FORMAT = "%Y:%m:%d"
80
79
 
81
80
  def capitalize(string)
@@ -96,6 +95,7 @@ class SwissmedicDiff
96
95
  txt = FLAGS.fetch(flag, flag)
97
96
  case flag
98
97
  when :sequence
98
+ txt
99
99
  when :replaced_package
100
100
  pairs = diff.newest_rows[iksnr].collect { |rep, row|
101
101
  if (old = diff.replacements[row])
@@ -104,15 +104,15 @@ class SwissmedicDiff
104
104
  }.compact
105
105
  sprintf "%s (%s)", txt, pairs.join(",")
106
106
  when :registration_date, :expiry_date
107
- row = diff.newest_rows[iksnr].sort.first.last
108
- if row[COLUMNS_2014.keys.index(flag)].to_s.match(REGEXP_UNLIMITED)
107
+ row = diff.newest_rows[iksnr].min.last
108
+ if row[COLUMNS_FEBRUARY_2019.keys.index(flag)].to_s.match(REGEXP_UNLIMITED)
109
109
  sprintf "%s (%s)", txt, "unbegrenzt"
110
110
  else
111
- sprintf "%s (%s)", txt, row[COLUMNS_2014.keys.index(flag)].strftime("%d.%m.%Y")
111
+ sprintf "%s (%s)", txt, row[COLUMNS_FEBRUARY_2019.keys.index(flag)].strftime("%d.%m.%Y")
112
112
  end
113
113
  else
114
- row = diff.newest_rows[iksnr].sort.first.last
115
- sprintf "%s (%s)", txt, cell(row, COLUMNS_2014.keys.index(flag))
114
+ row = diff.newest_rows[iksnr].min.last
115
+ sprintf "%s (%s)", txt, cell(row, COLUMNS_FEBRUARY_2019.keys.index(flag))
116
116
  end
117
117
  end
118
118
 
@@ -144,7 +144,7 @@ class SwissmedicDiff
144
144
  multiples[iksnr] ||= {}
145
145
  if prr == iksnr && prp == pacnr
146
146
  idx += 1
147
- elsif previous = multiples[iksnr][pacnr]
147
+ elsif (previous = multiples[iksnr][pacnr])
148
148
  prr = iksnr
149
149
  prp = pacnr
150
150
  idx = previous[@target_keys.size].to_i + 1
@@ -194,9 +194,17 @@ class SwissmedicDiff
194
194
  }
195
195
  @diff.sequence_deletions = known_seqs.keys
196
196
  @diff.registration_deletions = known_regs.keys
197
+ @@stat = {}
198
+ @@stat[:target] = "#{File.basename(target)} #{File.size(target)} bytes"
199
+ @@stat[:latest] = "#{File.basename(latest)} #{File.size(latest)} bytes"
200
+ @diff.to_h.keys.each { |name| @diff.instance_eval("@@stat[:#{name}] = #{name}.size", __FILE__, __LINE__) }
197
201
  @diff
198
202
  end
199
203
 
204
+ def SwissmedicDiff.stat
205
+ @@stat
206
+ end
207
+
200
208
  def format_flags(flags)
201
209
  flags.delete(:revision)
202
210
  flags.collect { |flag|
@@ -227,7 +235,7 @@ class SwissmedicDiff
227
235
  multiples[iksnr] ||= {}
228
236
  if prr == iksnr && prp == pacnr
229
237
  idx += 1
230
- elsif previous = multiples[iksnr][pacnr]
238
+ elsif (previous = multiples[iksnr][pacnr])
231
239
  prr = iksnr
232
240
  prp = pacnr
233
241
  idx = previous[@latest_keys.size].to_i + 1
@@ -247,8 +255,8 @@ class SwissmedicDiff
247
255
 
248
256
  def name(diff, iksnr)
249
257
  rows = diff.newest_rows[iksnr]
250
- row = rows.sort.first.last
251
- cell(row, COLUMNS_2014.keys.index(:name_base))
258
+ row = rows.min.last
259
+ cell(row, COLUMNS_FEBRUARY_2019.keys.index(:name_base))
252
260
  end
253
261
 
254
262
  def rows_diff(row, other, ignore = [])
@@ -316,7 +324,7 @@ class SwissmedicDiff
316
324
  if row[idx]
317
325
  case key
318
326
  when :registration_date, :expiry_date
319
- if row[idx] && row[idx] && REGEXP_UNLIMITED.match(row[idx].to_s)
327
+ if row[idx] && REGEXP_UNLIMITED.match(row[idx].to_s)
320
328
  VALUE_UNLIMITED # Date.new(2099,12,31)
321
329
  else
322
330
  row[idx]
@@ -330,8 +338,8 @@ class SwissmedicDiff
330
338
  end
331
339
 
332
340
  def get_column_indices(rows)
333
- headerRowId = rows_to_skip(rows) - 1
334
- rows[headerRowId]
341
+ header_row_id = rows_to_skip(rows) - 1
342
+ rows[header_row_id]
335
343
  row = rows[5] # Headers are found at row 5 since February 5
336
344
  0.upto(COLUMNS_FEBRUARY_2019.size - 1).each { |idx| puts "#{idx}: #{row[idx]}" } if $VERBOSE
337
345
  COLUMNS_FEBRUARY_2019.each { |key, value|
@@ -358,12 +366,12 @@ class SwissmedicDiff
358
366
  #
359
367
  # return ::
360
368
  def each_valid_row(rows)
361
- skipRows = rows_to_skip(rows)
369
+ skip_rows = rows_to_skip(rows)
362
370
  column_keys = get_column_indices(rows).keys
363
371
  row_nr = 0
364
372
  rows.each { |row|
365
373
  row_nr += 1
366
- next if row_nr <= skipRows
374
+ next if row_nr <= skip_rows
367
375
  break unless row
368
376
  if row.size < column_keys.size / 2
369
377
  $stdout.puts "Data missing in \n(line " + row_nr.to_s + "): " + row.join(", ").to_s + "\n"
@@ -379,9 +387,9 @@ class SwissmedicDiff
379
387
 
380
388
  def rows_to_skip(rows)
381
389
  j = 0
382
- while true
390
+ loop do
383
391
  cell = rows[j][0]
384
- break if cell.respond_to?(:to_i) and cell.to_i != 0
392
+ break if cell.respond_to?(:to_i) && cell.to_i != 0
385
393
  j += 1
386
394
  end
387
395
  j
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class SwissmedicDiff
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # SwissmedicPluginTest -- oddb.org -- 18.03.2008 -- hwyss@ywesee.com
4
+
5
+ $: << File.expand_path("../lib", File.dirname(__FILE__))
6
+
7
+ require "minitest/autorun"
8
+ require "tempfile"
9
+ require "open3"
10
+
11
+ module ODDB
12
+ class SwissmedicPluginBinTest < Minitest::Test
13
+ def test_running_binary
14
+ cmd = "bundle exec ruby bin/swissmedic-diff test/data/Packungen-2025.07.01.xlsx test/data/Packungen-2019.03.06.xlsx"
15
+ stdout, stderr, status = Open3.capture3(cmd)
16
+ puts "Output: #{stdout}"
17
+ puts "Error: #{stderr}" if stderr
18
+ puts "Exit Status: #{status.exitstatus}"
19
+ assert_equal(0, status.exitstatus)
20
+ lines = stdout.split("\n")
21
+ assert_equal(40, lines.size)
22
+ found = lines.find { |line| line.eql?("+ 16105: Hirudoid, Creme") }
23
+ assert(found, "Must find + 16105: Hirudoid, Creme")
24
+ found = lines.find { |line| line.eql?("> 44447: Lopresor Retard 200, Divitabs; Namensänderung (Lopresor Retard 200, Divitabs), Heilmittelcode (Synthetika human), Ablaufdatum der Zulassung (22.12.2019), Wirkstoffe (metoprololi tartras (2:1)), Zusammensetzung (metoprololi tartras (2:1) 200 mg, excipiens pro compresso obducto.)") }
25
+ assert(found, "must found Ablaufdatum")
26
+ end
27
+ end
28
+ end
@@ -14,6 +14,28 @@ module ODDB
14
14
  @diff = SwissmedicDiff.new
15
15
  end
16
16
 
17
+ def test_diff_changes_january_2026
18
+ start_time = Time.now
19
+ @diff = SwissmedicDiff.new
20
+ last_month = File.expand_path "data/Packungen-2025.12.15.xlsx", File.dirname(__FILE__)
21
+ this_month = File.expand_path "data/Packungen-2026.01.08.xlsx", File.dirname(__FILE__)
22
+ result = @diff.diff this_month, last_month
23
+ duration = (Time.now - start_time).to_i
24
+ puts "Took #{duration} seconds"
25
+ assert_equal(487, result.updates.size)
26
+ assert_equal(336, result.changes.size)
27
+ assert_equal(148, result.news.size)
28
+ assert_equal(7, result.replacements.size)
29
+ assert_equal(107, result.package_deletions.size)
30
+
31
+ assert_equal(["16105", "01", "Hirudoid, Creme", "Medinova AG", "Synthetika", "02.08.2.", "C05BA01", Date.new(1951, 9, 1), Date.new(1951, 9, 1), "unbegrenzt", "001", "14", "g", "D", "D", "D", "heparinoidum (chondroitini polysulfas)", "heparinoidum (chondroitini polysulfas) 3 mg, corresp. 250 U., glycerolum (85 per centum), acidum stearicum, alcoholes adipis lanae, alcohol cetylicus et stearylicus 31.375 mg, vaselinum album, alcohol myristylicus, alcohol isopropylicus, kalii hydroxidum, E 218 1.6 mg, thymolum, propylis parahydroxybenzoas 0.4 mg, aqua purificata, ad unguentum pro 1 g.", "X", "Venenmittel für den äusserlichen Gebrauch", nil, nil, nil, nil, 0], result.news.first)
32
+
33
+ assert_equal([["55249", "01", "Bronchosan Husten, Tropfen zum Einnehmen", "A.Vogel AG", "Phytoarzneimittel", "03.02.0.", "R05CA10", Date.new(2000, 10, 18), Date.new(2000, 10, 18), "unbegrenzt", "001", "50", "ml", "D", "D", "D", "hederae helicis herbae recentis tinctura (Hedera helix L., herba), thymi herbae recentis tinctura (Thymus vulgaris L., herba), liquiritiae radicis tinctura (Glycyrrhiza glabra L., radix)", "hederae helicis herbae recentis tinctura (Hedera helix L., herba) 376.1 mg, ratio: 1:5.6, Auszugsmittel ethanolum 50.6% (V/V), thymi herbae recentis tinctura (Thymus vulgaris L., herba) 329.1 mg, ratio: 1:7.9, Auszugsmittel ethanolum 50.6% (V/V), liquiritiae radicis tinctura (Glycyrrhiza glabra L., radix) 233.9 mg, ratio: 1:10, Auszugsmittel ethanolum 50.6% (V/V), anisi stellati aetheroleum, eucalypti aetheroleum, ad solutionem pro 1 ml, corresp. ethanolum 51 % V/V.", "X", "Bei Erkältungshusten", nil, nil, nil, nil, 0], "052"], result.replacements.first)
34
+
35
+ assert_equal(["00613", [:expiry_date]], result.changes.first)
36
+ assert_equal({target: "Packungen-2026.01.08.xlsx 3198082 bytes", latest: "Packungen-2025.12.15.xlsx 3218271 bytes", news: 148, updates: 487, changes: 336, newest_rows: 6305, replacements: 147, package_deletions: 107, sequence_deletions: 60, registration_deletions: 47}, SwissmedicDiff.stat)
37
+ end
38
+
17
39
  def test_diff_changes_february_2019
18
40
  @diff = SwissmedicDiff.new
19
41
  last_month = File.expand_path "data/Packungen-2019.03.06.xlsx", File.dirname(__FILE__)
@@ -61,6 +83,7 @@ module ODDB
61
83
 
62
84
  result = @diff.diff this_month, last_month
63
85
  assert_equal(expected, result.changes)
86
+ assert_equal({target: "Packungen-2025.07.01.xlsx 245310 bytes", latest: "Packungen-2019.03.06.xlsx 347989 bytes", news: 41, updates: 2, changes: 40, newest_rows: 40, replacements: 9, package_deletions: 39, sequence_deletions: 34, registration_deletions: 32}, SwissmedicDiff.stat)
64
87
  end
65
88
  end
66
89
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: swissmedic-diff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hannes Wyss, Masaomi Hatakeyama
@@ -164,11 +164,14 @@ files:
164
164
  - Manifest.txt
165
165
  - Packungen-2023.08.08.xlsx
166
166
  - Packungen-2023.09.08.xlsx
167
+ - Packungen-2025.12.15.xlsx
168
+ - Packungen-2026.01.08.xlsx
167
169
  - README.md
168
170
  - Rakefile
169
171
  - bin/swissmedic-diff
170
172
  - lib/swissmedic-diff.rb
171
173
  - lib/version.rb
174
+ - test/test_swissmedic-diff-bin.rb
172
175
  - test/test_swissmedic-diff.rb
173
176
  homepage: https://github.com/zdavatz/swissmedic-diff
174
177
  licenses:
@@ -182,14 +185,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
182
185
  requirements:
183
186
  - - ">="
184
187
  - !ruby/object:Gem::Version
185
- version: '2.0'
188
+ version: '2.6'
186
189
  required_rubygems_version: !ruby/object:Gem::Requirement
187
190
  requirements:
188
191
  - - ">="
189
192
  - !ruby/object:Gem::Version
190
193
  version: '0'
191
194
  requirements: []
192
- rubygems_version: 3.6.2
195
+ rubygems_version: 4.0.3
193
196
  specification_version: 4
194
197
  summary: Find out what Products have changed on the swiss healthcare market
195
198
  test_files: