relaton 1.6.0 → 1.7.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/docs/README.adoc +228 -2
  3. data/globalcache/iec/iec_60050_102_2007.xml +58 -0
  4. data/globalcache/iec/version +1 -0
  5. data/lib/relaton.rb +8 -7
  6. data/lib/relaton/config.rb +3 -2
  7. data/lib/relaton/db.rb +237 -32
  8. data/lib/relaton/db_cache.rb +32 -7
  9. data/lib/relaton/processor.rb +11 -0
  10. data/lib/relaton/registry.rb +1 -1
  11. data/lib/relaton/version.rb +1 -1
  12. data/lib/relaton/workers_pool.rb +23 -0
  13. data/localcache/iec/iec_60050_102_2007.xml +58 -0
  14. data/localcache/iec/version +1 -0
  15. data/relaton.gemspec +15 -14
  16. data/spec/relaton/db_cache_spec.rb +26 -1
  17. data/spec/relaton/db_spec.rb +122 -0
  18. data/spec/relaton/processor_spec.rb +4 -0
  19. data/spec/relaton/regirtry_spec.rb +7 -3
  20. data/spec/relaton_spec.rb +114 -20
  21. data/spec/vcr_cassetes/19133_2005.yml +17 -17
  22. data/spec/vcr_cassetes/cc_dir_10005_2019.yml +8 -8
  23. data/spec/vcr_cassetes/ecma_6.yml +94 -0
  24. data/spec/vcr_cassetes/fisp_140.yml +6 -6
  25. data/spec/vcr_cassetes/gb_t_20223_2006.yml +13 -9
  26. data/spec/vcr_cassetes/hist_cmbined_included.yml +105 -0
  27. data/spec/vcr_cassetes/iec_60050_102_2007.yml +281 -0
  28. data/spec/vcr_cassetes/iec_combined_included.yml +945 -0
  29. data/spec/vcr_cassetes/ieee_528_2019.yml +12 -12
  30. data/spec/vcr_cassetes/iho_b_11.yml +15 -15
  31. data/spec/vcr_cassetes/iso_111111119115_1.yml +3 -3
  32. data/spec/vcr_cassetes/iso_19115.yml +18 -18
  33. data/spec/vcr_cassetes/iso_19115_1.yml +19 -19
  34. data/spec/vcr_cassetes/iso_19115_1_2.yml +33 -33
  35. data/spec/vcr_cassetes/iso_awi_24229.yml +18 -18
  36. data/spec/vcr_cassetes/iso_combined_applied.yml +361 -0
  37. data/spec/vcr_cassetes/iso_combined_included.yml +361 -0
  38. data/spec/vcr_cassetes/itu_combined_included.yml +1296 -0
  39. data/spec/vcr_cassetes/ogc_19_025r1.yml +2307 -1909
  40. data/spec/vcr_cassetes/ogm_ami4ccm_1_0.yml +7 -7
  41. data/spec/vcr_cassetes/rfc_8341.yml +47 -15
  42. data/spec/vcr_cassetes/rfc_unsuccess.yml +70 -0
  43. data/spec/vcr_cassetes/sp_800_38b.yml +6 -6
  44. data/spec/vcr_cassetes/un_rtade_cefact_2004_32.yml +35 -31
  45. data/spec/vcr_cassetes/w3c_json_ld11.yml +18 -12
  46. metadata +65 -38
@@ -1,4 +1,5 @@
1
1
  require "fileutils"
2
+ require "timeout"
2
3
 
3
4
  module Relaton
4
5
  class DbCache
@@ -14,6 +15,20 @@ module Relaton
14
15
  # set_version # unless File.exist? file_version
15
16
  end
16
17
 
18
+ # Move caches to anothe dir
19
+ # @param new_dir [String, nil]
20
+ def mv(new_dir)
21
+ return unless new_dir && @ext == "xml"
22
+
23
+ FileUtils.mv dir, new_dir
24
+ @dir = new_dir
25
+ end
26
+
27
+ # Clear database
28
+ def clear
29
+ FileUtils.rm_rf Dir.glob "#{dir}/*" if @ext == "xml" # unless it's static DB
30
+ end
31
+
17
32
  # Save item
18
33
  # @param key [String]
19
34
  # @param value [String] Bibitem xml serialization
@@ -26,7 +41,7 @@ module Relaton
26
41
  prefix_dir = "#{@dir}/#{prefix(key)}"
27
42
  FileUtils::mkdir_p prefix_dir unless Dir.exist? prefix_dir
28
43
  set_version prefix_dir
29
- File.write "#{filename(key)}.#{ext(value)}", value, encoding: "utf-8"
44
+ file_safe_write "#{filename(key)}.#{ext(value)}", value
30
45
  end
31
46
 
32
47
  # @param value [String]
@@ -65,7 +80,7 @@ module Relaton
65
80
  value = self[key]
66
81
  return unless value
67
82
 
68
- if value =~ /^not_found/
83
+ if value.match? /^not_found/
69
84
  value.match(/\d{4}-\d{2}-\d{2}/).to_s
70
85
  else
71
86
  doc = Nokogiri::XML value
@@ -76,8 +91,9 @@ module Relaton
76
91
  # Returns all items
77
92
  # @return [Array<String>]
78
93
  def all
79
- Dir.glob("#{@dir}/**/*.xml").sort.map do |f|
80
- File.read(f, encoding: "utf-8")
94
+ Dir.glob("#{@dir}/**/*.{xml,yml,yaml}").sort.map do |f|
95
+ content = File.read(f, encoding: "utf-8")
96
+ block_given? ? yield(f, content) : content
81
97
  end
82
98
  end
83
99
 
@@ -106,7 +122,7 @@ module Relaton
106
122
  def set_version(fdir)
107
123
  file_version = "#{fdir}/version"
108
124
  unless File.exist? file_version
109
- File.write file_version, grammar_hash(fdir), encoding: "utf-8"
125
+ file_safe_write file_version, grammar_hash(fdir)
110
126
  end
111
127
  self
112
128
  end
@@ -159,7 +175,7 @@ module Relaton
159
175
  def filename(key)
160
176
  prefcode = key.downcase.match /^(?<prefix>[^\(]+)\((?<code>[^\)]+)/
161
177
  fn = if prefcode
162
- "#{prefcode[:prefix]}/#{prefcode[:code].gsub(/[-:\s\/\()]/, '_').squeeze("_")}"
178
+ "#{prefcode[:prefix]}/#{prefcode[:code].gsub(/[-:\s\/\()]/, '_').squeeze('_')}"
163
179
  else
164
180
  key.gsub(/[-:\s]/, "_")
165
181
  end
@@ -189,6 +205,15 @@ module Relaton
189
205
  key.downcase.match(/^[^\(]+(?=\()/).to_s
190
206
  end
191
207
 
208
+ # @param file [String]
209
+ # @content [String]
210
+ def file_safe_write(file, content)
211
+ File.open file, File::RDWR | File::CREAT, encoding: "UTF-8" do |f|
212
+ Timeout.timeout(10) { f.flock File::LOCK_EX }
213
+ f.write content
214
+ end
215
+ end
216
+
192
217
  class << self
193
218
  private
194
219
 
@@ -209,7 +234,7 @@ module Relaton
209
234
  # local_cache: local cache name; none created if nil; "relaton" created
210
235
  # if empty global_cache: boolean to create global_cache
211
236
  # flush_caches: flush caches
212
- def init_bib_caches(opts)
237
+ def init_bib_caches(opts) # rubocop:disable Metrics/CyclomaticComplexity
213
238
  globalname = global_bibliocache_name if opts[:global_cache]
214
239
  localname = local_bibliocache_name(opts[:local_cache])
215
240
  localname = "relaton" if localname&.empty?
@@ -20,5 +20,16 @@ module Relaton
20
20
  def hash_to_bib(_hash)
21
21
  raise "This is an abstract class!"
22
22
  end
23
+
24
+ def grammar_hash
25
+ raise "This is an abstract class!"
26
+ end
27
+
28
+ # Retuns default number of workers. Should be overraded by childred classes if need.
29
+ #
30
+ # @return [Integer] nuber of wokrers
31
+ def threads
32
+ 10
33
+ end
23
34
  end
24
35
  end
@@ -8,7 +8,7 @@ module Relaton
8
8
  SUPPORTED_GEMS = %w[
9
9
  relaton_gb relaton_iec relaton_ietf relaton_iso relaton_itu relaton_nist
10
10
  relaton_ogc relaton_calconnect relaton_omg relaton_un relaton_w3c
11
- relaton_ieee relaton_iho relaton_bipm
11
+ relaton_ieee relaton_iho relaton_bipm relaton_ecma
12
12
  ].freeze
13
13
 
14
14
  include Singleton
@@ -1,3 +1,3 @@
1
1
  module Relaton
2
- VERSION = "1.6.0".freeze
2
+ VERSION = "1.7.4".freeze
3
3
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Relaton
4
+ # Workers poll.
5
+ class WorkersPool
6
+ def initialize(workers = 2, &_block)
7
+ num_workers = workers < 2 ? 2 : workers
8
+ @queue = SizedQueue.new(num_workers * 2)
9
+ @threads = Array.new num_workers do
10
+ Thread.new do
11
+ while item = @queue.pop
12
+ yield(item)
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ def <<(item)
19
+ @queue << item
20
+ self
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,58 @@
1
+ <bibdata type="standard">
2
+ <fetched>2021-02-03</fetched>
3
+ <title type="title-main" format="text/plain" language="en" script="Latn">International Electrotechnical Vocabulary (IEV)</title>
4
+ <title type="title-part" format="text/plain" language="en" script="Latn">Part 102: Mathematics -- General concepts and linear algebra</title>
5
+ <title type="main" format="text/plain" language="en" script="Latn">International Electrotechnical Vocabulary (IEV) - Part 102: Mathematics -- General concepts and linear algebra</title>
6
+ <uri type="src">https://webstore.iec.ch/publication/160</uri>
7
+ <uri type="obp">/preview/info_iec60050-102%7Bed1.0%7Db.pdf</uri>
8
+ <docidentifier type="IEC">IEC 60050-102:2007</docidentifier>
9
+ <docidentifier type="URN">urn:iec:std:iec:60050-102:2007:::en</docidentifier>
10
+ <date type="published">
11
+ <on>2007-08-27</on>
12
+ </date>
13
+ <contributor>
14
+ <role type="publisher"/>
15
+ <organization>
16
+ <name>International Electrotechnical Commission</name>
17
+ <abbreviation>IEC</abbreviation>
18
+ <uri>www.iec.ch</uri>
19
+ </organization>
20
+ </contributor>
21
+ <edition>1.0</edition>
22
+ <language>en</language>
23
+ <script>Latn</script>
24
+ <abstract format="text/plain" language="en" script="Latn">This part of IEC 60050 gives the general mathematical terminology used in the fields of electricity, electronics and telecommunications, together with basic concepts in linear algebra. It maintains a clear distinction between mathematical concepts and physical concepts, even if some terms are used in both cases. Another part will deal with functions.&#13;
25
+ It has the status of a horizontal standard in accordance with IEC Guide 108.</abstract>
26
+ <status>
27
+ <stage>60</stage>
28
+ <substage>60</substage>
29
+ </status>
30
+ <copyright>
31
+ <from>2007</from>
32
+ <owner>
33
+ <organization>
34
+ <name>International Electrotechnical Commission</name>
35
+ <abbreviation>IEC</abbreviation>
36
+ <uri>www.iec.ch</uri>
37
+ </organization>
38
+ </owner>
39
+ </copyright>
40
+ <place>Geneva</place>
41
+ <ext>
42
+ <doctype>international-standard</doctype>
43
+ <editorialgroup>
44
+ <technical-committee number="1" type="technicalCommittee">TC 1 - Terminology</technical-committee>
45
+ </editorialgroup>
46
+ <ics>
47
+ <code>01.040.07</code>
48
+ <text>Natural and applied sciences (Vocabularies)</text>
49
+ </ics>
50
+ <ics>
51
+ <code>07.020</code>
52
+ <text>Mathematics</text>
53
+ </ics>
54
+ <structuredidentifier type="IEC">
55
+ <project-number>60050</project-number>
56
+ </structuredidentifier>
57
+ </ext>
58
+ </bibdata>
@@ -0,0 +1 @@
1
+ 407d6f5afdc9ae9ea7abe6e84d27f40b
data/relaton.gemspec CHANGED
@@ -30,20 +30,21 @@ Gem::Specification.new do |spec|
30
30
  spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
31
31
 
32
32
  # spec.add_dependency "algoliasearch"
33
- spec.add_dependency "relaton-bipm", "~> 1.6.0"
34
- spec.add_dependency "relaton-calconnect", "~> 1.6.0"
35
- spec.add_dependency "relaton-gb", "~> 1.6.0"
36
- spec.add_dependency "relaton-iec", "~> 1.6.0"
37
- spec.add_dependency "relaton-ieee", "~> 1.6.0"
38
- spec.add_dependency "relaton-ietf", "~> 1.6.0"
39
- spec.add_dependency "relaton-iho", "~> 1.6.0"
40
- spec.add_dependency "relaton-iso", "~> 1.6.0"
41
- spec.add_dependency "relaton-itu", "~> 1.6.0"
42
- spec.add_dependency "relaton-nist", "~> 1.6.0"
43
- spec.add_dependency "relaton-ogc", "~> 1.6.0"
44
- spec.add_dependency "relaton-omg", "~> 1.6.0"
45
- spec.add_dependency "relaton-un", "~> 1.6.0"
46
- spec.add_dependency "relaton-w3c", "~> 1.6.0"
33
+ spec.add_dependency "relaton-bipm", "~> 1.7.0"
34
+ spec.add_dependency "relaton-calconnect", "~> 1.7.0"
35
+ spec.add_dependency "relaton-ecma", "1.7.pre1"
36
+ spec.add_dependency "relaton-gb", "~> 1.7.0"
37
+ spec.add_dependency "relaton-iec", ">= 1.7.6"
38
+ spec.add_dependency "relaton-ieee", "~> 1.7.0"
39
+ spec.add_dependency "relaton-ietf", "~> 1.7.0"
40
+ spec.add_dependency "relaton-iho", "~> 1.7.0"
41
+ spec.add_dependency "relaton-iso", ">= 1.7.1"
42
+ spec.add_dependency "relaton-itu", ">= 1.7.2"
43
+ spec.add_dependency "relaton-nist", ">= 1.7.1"
44
+ spec.add_dependency "relaton-ogc", "~> 1.7.0"
45
+ spec.add_dependency "relaton-omg", "~> 1.7.0"
46
+ spec.add_dependency "relaton-un", "~> 1.7.0"
47
+ spec.add_dependency "relaton-w3c", "~> 1.7.0"
47
48
 
48
49
  spec.add_development_dependency "byebug", "~> 11.0"
49
50
  spec.add_development_dependency "debase"
@@ -1,13 +1,38 @@
1
+ require "fileutils"
2
+ require "timeout"
3
+
1
4
  RSpec.describe Relaton::DbCache do
2
5
  it "creates default caches" do
3
6
  cache_path = File.expand_path("~/.relaton/cache")
4
7
  FileUtils.mv cache_path, "relaton1/cache", force: true
5
8
  FileUtils.rm_rf %w(relaton)
6
9
  Relaton::DbCache.init_bib_caches(
7
- global_cache: true, local_cache: "", flush_caches: true,
10
+ global_cache: true, local_cache: "", flush_caches: true
8
11
  )
9
12
  expect(File.exist?(cache_path)).to be true
10
13
  expect(File.exist?("relaton")).to be true
11
14
  FileUtils.mv "relaton1/cache", cache_path if File.exist? "relaton1"
12
15
  end
16
+
17
+ it "write same file by concurent processes" do
18
+ dir = "testcache/iso"
19
+ FileUtils.mkdir_p dir unless File.exist? dir
20
+ file_name = File.join dir, "iso_123.xml"
21
+ file = File.open file_name, File::RDWR | File::CREAT, encoding: "UTF-8"
22
+ file.flock File::LOCK_EX
23
+ command = <<~RBY
24
+ require "relaton"
25
+ cache = Relaton::DbCache.new "testcache"
26
+ cache["ISO(ISO 123)"] = "test 1"
27
+ RBY
28
+ pid = spawn RbConfig.ruby, "-e #{command}"
29
+ sleep 0.1
30
+ file.write "test 2"
31
+ file.flock File::LOCK_UN
32
+ file.close
33
+ Process.waitpid pid, 0
34
+ expect($?.exitstatus).to eq 0
35
+ expect(File.read(file_name)).to eq "test 1"
36
+ FileUtils.rm_rf "testcache"
37
+ end
13
38
  end
@@ -1,6 +1,98 @@
1
1
  RSpec.describe Relaton::Db do
2
2
  before(:each) { FileUtils.rm_rf %w[testcache testcache2] }
3
3
 
4
+ context "modifing database" do
5
+ it "move to new dir" do
6
+ db = Relaton::Db.new "global_cache", "local_cache"
7
+ db.save_entry "ISO(ISO 123)", "<bibitem id='ISO123></bibitem>"
8
+ expect(File.exist?("global_cache")).to be true
9
+ expect(File.exist?("local_cache")).to be true
10
+ db.mv "testcache", "testcache2"
11
+ expect(File.exist?("testcache")).to be true
12
+ expect(File.exist?("global_cache")).to be false
13
+ expect(File.exist?("testcache2")).to be true
14
+ expect(File.exist?("local_cache")).to be false
15
+ end
16
+
17
+ it "clear" do
18
+ db = Relaton::Db.new "testcache", "testcache2"
19
+ db.save_entry "ISO(ISO 123)", "<bibitem id='ISO123></bibitem>"
20
+ expect(File.exist?("testcache/iso")).to be true
21
+ expect(File.exist?("testcache2/iso")).to be true
22
+ db.clear
23
+ expect(File.exist?("testcache/iso")).to be false
24
+ expect(File.exist?("testcache2/iso")).to be false
25
+ end
26
+ end
27
+
28
+ context "query in local DB" do
29
+ let(:db) { Relaton::Db.new "testcache", "testcache2" }
30
+
31
+ before(:each) do
32
+ db.save_entry "ISO(ISO 123)", <<~DOC
33
+ <bibitem id='ISO123'>
34
+ <title>The first test</title><edition>2</edition><date type="published"><on>2011-10-12</on></date>
35
+ </bibitem>
36
+ DOC
37
+ db.save_entry "IEC(IEC 123)", <<~DOC
38
+ <bibitem id="IEC123">
39
+ <title>The second test</title><edition>1</edition><date type="published"><on>2015-12</on></date>
40
+ </bibitem>
41
+ DOC
42
+ end
43
+
44
+ after(:each) { db.clear }
45
+
46
+ it "one document" do
47
+ item = db.fetch_db "ISO((ISO 124)"
48
+ expect(item).to be_nil
49
+ item = db.fetch_db "ISO(ISO 123)"
50
+ expect(item).to be_instance_of RelatonIsoBib::IsoBibliographicItem
51
+ end
52
+
53
+ it "all documents" do
54
+ items = db.fetch_all
55
+ expect(items.size).to be 9
56
+ expect(items[7]).to be_instance_of RelatonIec::IecBibliographicItem
57
+ expect(items[8]).to be_instance_of RelatonIsoBib::IsoBibliographicItem
58
+ end
59
+
60
+ context "search for text" do
61
+ it do
62
+ items = db.fetch_all "test"
63
+ expect(items.size).to eq 2
64
+ items = db.fetch_all "first"
65
+ expect(items.size).to eq 1
66
+ expect(items[0].id).to eq "ISO123"
67
+ end
68
+
69
+ it "in attributes" do
70
+ items = db.fetch_all "123"
71
+ expect(items.size).to eq 2
72
+ items = db.fetch_all "ISO"
73
+ expect(items.size).to eq 8
74
+ expect(items[7].id).to eq "ISO123"
75
+ end
76
+
77
+ it "and fail" do
78
+ items = db.fetch_all "bibitem"
79
+ expect(items.size).to eq 0
80
+ end
81
+
82
+ it "and edition" do
83
+ items = db.fetch_all "123", edition: "2"
84
+ expect(items.size).to eq 1
85
+ expect(items[0].id).to eq "ISO123"
86
+ end
87
+
88
+ it "and year" do
89
+ items = db.fetch_all "123", year: 2015
90
+ expect(items.size).to eq 1
91
+ expect(items[0].id).to eq "IEC123"
92
+ end
93
+ end
94
+ end
95
+
4
96
  it "returns docid type" do
5
97
  db = Relaton::Db.new "testcache", "testcache2"
6
98
  expect(db.docid_type("CN(GB/T 1.1)")).to eq ["Chinese Standard", "GB/T 1.1"]
@@ -30,6 +122,36 @@ RSpec.describe Relaton::Db do
30
122
  end
31
123
  end
32
124
 
125
+ it "fetch document with net retries" do
126
+ db = Relaton::Db.new nil, nil
127
+ expect(db.instance_variable_get(:@registry).processors[:relaton_ietf]).to receive(:get)
128
+ .and_raise(RelatonBib::RequestError).exactly(3).times
129
+ expect { db.fetch "RFC 8341", nil, retries: 3 }.to raise_error RelatonBib::RequestError
130
+ end
131
+
132
+ context "async fetch" do
133
+ let(:db) { Relaton::Db.new nil, nil }
134
+ let(:queue) { Queue.new }
135
+
136
+ it "success" do
137
+ result = nil
138
+ VCR.use_cassette "rfc_8341" do
139
+ db.fetch_async("RFC 8341") { |r| queue << r }
140
+ Timeout.timeout(5) { result = queue.pop }
141
+ end
142
+ expect(result).to be_instance_of RelatonIetf::IetfBibliographicItem
143
+ end
144
+
145
+ it "prefix not found" do
146
+ result = ""
147
+ VCR.use_cassette "rfc_unsuccess" do
148
+ db.fetch_async("ABC 123456") { |r| queue << r }
149
+ Timeout.timeout(5) { result = queue.pop }
150
+ end
151
+ expect(result).to be_nil
152
+ end
153
+ end
154
+
33
155
  context "fetch documents form static cache" do
34
156
  let(:db) { Relaton::Db.new nil, nil }
35
157
 
@@ -23,5 +23,9 @@ RSpec.describe Relaton::Processor do
23
23
  it "hash_to_bib method should be implemented" do
24
24
  expect { subject.hash_to_bib({}) }.to raise_error StandardError
25
25
  end
26
+
27
+ it "grammar_hash method should be implemented" do
28
+ expect { subject.grammar_hash }.to raise_error StandardError
29
+ end
26
30
  end
27
31
  end
@@ -2,13 +2,13 @@ RSpec.describe Relaton::Registry do
2
2
  it "outputs backend not present" do
3
3
  stub_const "Relaton::Registry::SUPPORTED_GEMS", ["not_supported_gem"]
4
4
  expect { Relaton::Registry.clone.instance }.to output(
5
- /backend not_supported_gem not present/,
5
+ /backend not_supported_gem not present/
6
6
  ).to_stdout
7
7
  end
8
8
 
9
9
  it "finds ISO processor" do
10
- expect(Relaton::Registry.instance.find_processor("relaton_iso")).
11
- to be_instance_of RelatonIso::Processor
10
+ expect(Relaton::Registry.instance.find_processor("relaton_iso"))
11
+ .to be_instance_of RelatonIso::Processor
12
12
  end
13
13
 
14
14
  it "returns supported processors" do
@@ -70,4 +70,8 @@ RSpec.describe Relaton::Registry do
70
70
  it "finds processor by type" do
71
71
  expect(Relaton::Registry.instance.by_type("BIPM")).to be_instance_of RelatonBipm::Processor
72
72
  end
73
+
74
+ it "finds processor by type" do
75
+ expect(Relaton::Registry.instance.by_type("ECMA")).to be_instance_of RelatonEcma::Processor
76
+ end
73
77
  end