unitsdb 2.1.1 → 2.2.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 +4 -4
- data/.github/workflows/release.yml +8 -1
- data/.gitignore +2 -0
- data/.gitmodules +4 -3
- data/.rubocop.yml +13 -8
- data/.rubocop_todo.yml +217 -100
- data/CLAUDE.md +55 -0
- data/Gemfile +4 -1
- data/README.adoc +283 -16
- data/data/dimensions.yaml +1864 -0
- data/data/prefixes.yaml +874 -0
- data/data/quantities.yaml +3715 -0
- data/data/scales.yaml +97 -0
- data/data/schemas/dimensions-schema.yaml +153 -0
- data/data/schemas/prefixes-schema.yaml +155 -0
- data/data/schemas/quantities-schema.yaml +117 -0
- data/data/schemas/scales-schema.yaml +106 -0
- data/data/schemas/unit_systems-schema.yaml +116 -0
- data/data/schemas/units-schema.yaml +215 -0
- data/data/unit_systems.yaml +78 -0
- data/data/units.yaml +14052 -0
- data/exe/unitsdb +7 -1
- data/lib/unitsdb/cli.rb +42 -15
- data/lib/unitsdb/commands/_modify.rb +40 -4
- data/lib/unitsdb/commands/base.rb +6 -2
- data/lib/unitsdb/commands/check_si/si_formatter.rb +488 -0
- data/lib/unitsdb/commands/check_si/si_matcher.rb +487 -0
- data/lib/unitsdb/commands/check_si/si_ttl_parser.rb +103 -0
- data/lib/unitsdb/commands/check_si/si_updater.rb +254 -0
- data/lib/unitsdb/commands/check_si.rb +54 -35
- data/lib/unitsdb/commands/get.rb +11 -10
- data/lib/unitsdb/commands/normalize.rb +21 -7
- data/lib/unitsdb/commands/qudt/check.rb +150 -0
- data/lib/unitsdb/commands/qudt/formatter.rb +194 -0
- data/lib/unitsdb/commands/qudt/matcher.rb +746 -0
- data/lib/unitsdb/commands/qudt/ttl_parser.rb +403 -0
- data/lib/unitsdb/commands/qudt/update.rb +126 -0
- data/lib/unitsdb/commands/qudt/updater.rb +189 -0
- data/lib/unitsdb/commands/qudt.rb +82 -0
- data/lib/unitsdb/commands/release.rb +12 -9
- data/lib/unitsdb/commands/search.rb +12 -11
- data/lib/unitsdb/commands/ucum/check.rb +42 -29
- data/lib/unitsdb/commands/ucum/formatter.rb +2 -1
- data/lib/unitsdb/commands/ucum/matcher.rb +23 -9
- data/lib/unitsdb/commands/ucum/update.rb +14 -13
- data/lib/unitsdb/commands/ucum/updater.rb +40 -6
- data/lib/unitsdb/commands/ucum/xml_parser.rb +0 -2
- data/lib/unitsdb/commands/ucum.rb +44 -4
- data/lib/unitsdb/commands/validate/identifiers.rb +2 -4
- data/lib/unitsdb/commands/validate/qudt_references.rb +111 -0
- data/lib/unitsdb/commands/validate/references.rb +36 -19
- data/lib/unitsdb/commands/validate/si_references.rb +3 -5
- data/lib/unitsdb/commands/validate/ucum_references.rb +105 -0
- data/lib/unitsdb/commands/validate.rb +67 -11
- data/lib/unitsdb/commands.rb +20 -0
- data/lib/unitsdb/database.rb +90 -52
- data/lib/unitsdb/dimension.rb +1 -4
- data/lib/unitsdb/dimension_details.rb +0 -1
- data/lib/unitsdb/dimensions.rb +0 -2
- data/lib/unitsdb/errors.rb +7 -0
- data/lib/unitsdb/prefix.rb +0 -4
- data/lib/unitsdb/prefix_reference.rb +0 -2
- data/lib/unitsdb/prefixes.rb +0 -1
- data/lib/unitsdb/quantities.rb +0 -2
- data/lib/unitsdb/quantity.rb +0 -6
- data/lib/unitsdb/qudt.rb +100 -0
- data/lib/unitsdb/root_unit_reference.rb +0 -3
- data/lib/unitsdb/scale.rb +0 -4
- data/lib/unitsdb/scale_reference.rb +0 -2
- data/lib/unitsdb/scales.rb +0 -2
- data/lib/unitsdb/si_derived_base.rb +0 -2
- data/lib/unitsdb/ucum.rb +14 -10
- data/lib/unitsdb/unit.rb +0 -10
- data/lib/unitsdb/unit_reference.rb +0 -2
- data/lib/unitsdb/unit_system.rb +1 -3
- data/lib/unitsdb/unit_system_reference.rb +0 -2
- data/lib/unitsdb/unit_systems.rb +0 -2
- data/lib/unitsdb/units.rb +0 -2
- data/lib/unitsdb/utils.rb +32 -21
- data/lib/unitsdb/version.rb +5 -1
- data/lib/unitsdb.rb +62 -14
- data/unitsdb.gemspec +6 -3
- metadata +52 -13
- data/lib/unitsdb/commands/si_formatter.rb +0 -485
- data/lib/unitsdb/commands/si_matcher.rb +0 -470
- data/lib/unitsdb/commands/si_ttl_parser.rb +0 -100
- data/lib/unitsdb/commands/si_updater.rb +0 -212
|
@@ -4,16 +4,28 @@ require "thor"
|
|
|
4
4
|
|
|
5
5
|
module Unitsdb
|
|
6
6
|
module Commands
|
|
7
|
+
module Validate
|
|
8
|
+
autoload :Identifiers, "unitsdb/commands/validate/identifiers"
|
|
9
|
+
autoload :QudtReferences, "unitsdb/commands/validate/qudt_references"
|
|
10
|
+
autoload :References, "unitsdb/commands/validate/references"
|
|
11
|
+
autoload :SiReferences, "unitsdb/commands/validate/si_references"
|
|
12
|
+
autoload :UcumReferences, "unitsdb/commands/validate/ucum_references"
|
|
13
|
+
end
|
|
14
|
+
|
|
7
15
|
class ValidateCommand < Thor
|
|
16
|
+
# Inherit trace option from parent CLI
|
|
17
|
+
class_option :trace, type: :boolean, default: false,
|
|
18
|
+
desc: "Show full backtrace on error"
|
|
19
|
+
|
|
8
20
|
desc "references", "Validate that all references exist"
|
|
9
|
-
option :debug_registry, type: :boolean,
|
|
21
|
+
option :debug_registry, type: :boolean,
|
|
22
|
+
desc: "Show registry contents for debugging"
|
|
10
23
|
option :database, type: :string, required: true, aliases: "-d",
|
|
11
24
|
desc: "Path to UnitsDB database (required)"
|
|
12
|
-
option :print_valid, type: :boolean, default: false,
|
|
25
|
+
option :print_valid, type: :boolean, default: false,
|
|
26
|
+
desc: "Print valid references too"
|
|
13
27
|
def references
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
Commands::Validate::References.new(options).run
|
|
28
|
+
run_command(Commands::Validate::References, options)
|
|
17
29
|
end
|
|
18
30
|
|
|
19
31
|
desc "identifiers", "Check for uniqueness of identifier fields"
|
|
@@ -21,19 +33,63 @@ module Unitsdb
|
|
|
21
33
|
desc: "Path to UnitsDB database (required)"
|
|
22
34
|
|
|
23
35
|
def identifiers
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
Commands::Validate::Identifiers.new(options).run
|
|
36
|
+
run_command(Commands::Validate::Identifiers, options)
|
|
27
37
|
end
|
|
28
38
|
|
|
29
|
-
desc "si_references",
|
|
39
|
+
desc "si_references",
|
|
40
|
+
"Validate that each SI digital framework reference is unique per entity type"
|
|
30
41
|
option :database, type: :string, required: true, aliases: "-d",
|
|
31
42
|
desc: "Path to UnitsDB database (required)"
|
|
32
43
|
|
|
33
44
|
def si_references
|
|
34
|
-
|
|
45
|
+
run_command(Commands::Validate::SiReferences, options)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
desc "qudt_references",
|
|
49
|
+
"Validate that each QUDT reference is unique per entity type"
|
|
50
|
+
option :database, type: :string, required: true, aliases: "-d",
|
|
51
|
+
desc: "Path to UnitsDB database (required)"
|
|
52
|
+
|
|
53
|
+
def qudt_references
|
|
54
|
+
run_command(Commands::Validate::QudtReferences, options)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
desc "ucum_references",
|
|
58
|
+
"Validate that each UCUM reference is unique per entity type"
|
|
59
|
+
option :database, type: :string, required: true, aliases: "-d",
|
|
60
|
+
desc: "Path to UnitsDB database (required)"
|
|
61
|
+
|
|
62
|
+
def ucum_references
|
|
63
|
+
run_command(Commands::Validate::UcumReferences, options)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def run_command(command_class, options)
|
|
69
|
+
command = command_class.new(options)
|
|
70
|
+
command.run
|
|
71
|
+
rescue Unitsdb::Errors::CLIRuntimeError => e
|
|
72
|
+
handle_cli_error(e)
|
|
73
|
+
rescue StandardError => e
|
|
74
|
+
handle_error(e)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def handle_cli_error(error)
|
|
78
|
+
if options[:trace]
|
|
79
|
+
raise error
|
|
80
|
+
else
|
|
81
|
+
warn "Error: #{error.message}"
|
|
82
|
+
exit 1
|
|
83
|
+
end
|
|
84
|
+
end
|
|
35
85
|
|
|
36
|
-
|
|
86
|
+
def handle_error(error)
|
|
87
|
+
if options[:trace]
|
|
88
|
+
raise error
|
|
89
|
+
else
|
|
90
|
+
warn "Error: #{error.message}"
|
|
91
|
+
exit 1
|
|
92
|
+
end
|
|
37
93
|
end
|
|
38
94
|
end
|
|
39
95
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unitsdb
|
|
4
|
+
module Commands
|
|
5
|
+
autoload :ModifyCommand, "unitsdb/commands/_modify"
|
|
6
|
+
autoload :Base, "unitsdb/commands/base"
|
|
7
|
+
autoload :CheckSi, "unitsdb/commands/check_si"
|
|
8
|
+
autoload :CheckSiCommand, "unitsdb/commands/check_si"
|
|
9
|
+
autoload :Get, "unitsdb/commands/get"
|
|
10
|
+
autoload :Normalize, "unitsdb/commands/normalize"
|
|
11
|
+
autoload :Qudt, "unitsdb/commands/qudt"
|
|
12
|
+
autoload :QudtCommand, "unitsdb/commands/qudt"
|
|
13
|
+
autoload :Release, "unitsdb/commands/release"
|
|
14
|
+
autoload :Search, "unitsdb/commands/search"
|
|
15
|
+
autoload :Ucum, "unitsdb/commands/ucum"
|
|
16
|
+
autoload :UcumCommand, "unitsdb/commands/ucum"
|
|
17
|
+
autoload :Validate, "unitsdb/commands/validate"
|
|
18
|
+
autoload :ValidateCommand, "unitsdb/commands/validate"
|
|
19
|
+
end
|
|
20
|
+
end
|
data/lib/unitsdb/database.rb
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "unit"
|
|
4
|
-
require_relative "prefix"
|
|
5
|
-
require_relative "quantity"
|
|
6
|
-
require_relative "dimension"
|
|
7
|
-
require_relative "unit_system"
|
|
8
|
-
require_relative "errors"
|
|
9
|
-
|
|
10
3
|
module Unitsdb
|
|
11
4
|
class Database < Lutaml::Model::Serializable
|
|
12
5
|
# model Config.model_for(:units)
|
|
@@ -25,7 +18,11 @@ module Unitsdb
|
|
|
25
18
|
# @return [Object, nil] the first entity with matching identifier or nil if not found
|
|
26
19
|
def find_by_type(id:, type:)
|
|
27
20
|
collection = send(type.to_s)
|
|
28
|
-
collection.find
|
|
21
|
+
collection.find do |entity|
|
|
22
|
+
entity.identifiers&.any? do |identifier|
|
|
23
|
+
identifier.id == id
|
|
24
|
+
end
|
|
25
|
+
end
|
|
29
26
|
end
|
|
30
27
|
|
|
31
28
|
# Find an entity by its identifier id across all entity types
|
|
@@ -33,7 +30,8 @@ module Unitsdb
|
|
|
33
30
|
# @param type [String, nil] optional identifier type to match
|
|
34
31
|
# @return [Object, nil] the first entity with matching identifier or nil if not found
|
|
35
32
|
def get_by_id(id:, type: nil)
|
|
36
|
-
%w[units prefixes quantities dimensions
|
|
33
|
+
%w[units prefixes quantities dimensions
|
|
34
|
+
unit_systems].each do |collection_name|
|
|
37
35
|
next unless respond_to?(collection_name)
|
|
38
36
|
|
|
39
37
|
collection = send(collection_name)
|
|
@@ -63,7 +61,12 @@ module Unitsdb
|
|
|
63
61
|
results = []
|
|
64
62
|
|
|
65
63
|
# Define which collections to search based on type parameter
|
|
66
|
-
collections =
|
|
64
|
+
collections = if type
|
|
65
|
+
[type.to_s]
|
|
66
|
+
else
|
|
67
|
+
%w[units prefixes quantities
|
|
68
|
+
dimensions unit_systems]
|
|
69
|
+
end
|
|
67
70
|
|
|
68
71
|
collections.each do |collection_name|
|
|
69
72
|
next unless respond_to?(collection_name)
|
|
@@ -71,7 +74,9 @@ module Unitsdb
|
|
|
71
74
|
collection = send(collection_name)
|
|
72
75
|
collection.each do |entity|
|
|
73
76
|
# Search in identifiers
|
|
74
|
-
if entity.identifiers&.any?
|
|
77
|
+
if entity.identifiers&.any? do |identifier|
|
|
78
|
+
identifier.id.to_s.downcase.include?(text.downcase)
|
|
79
|
+
end
|
|
75
80
|
results << entity
|
|
76
81
|
next
|
|
77
82
|
end
|
|
@@ -86,14 +91,14 @@ module Unitsdb
|
|
|
86
91
|
|
|
87
92
|
# Search in short description
|
|
88
93
|
if entity.respond_to?(:short) && entity.short &&
|
|
89
|
-
|
|
94
|
+
entity.short.to_s.downcase.include?(text.downcase)
|
|
90
95
|
results << entity
|
|
91
96
|
next
|
|
92
97
|
end
|
|
93
98
|
|
|
94
99
|
# Special case for prefix name (prefixes don't have names array)
|
|
95
100
|
next unless collection_name == "prefixes" && entity.respond_to?(:name) &&
|
|
96
|
-
|
|
101
|
+
entity.name.to_s.downcase.include?(text.downcase)
|
|
97
102
|
|
|
98
103
|
results << entity
|
|
99
104
|
next
|
|
@@ -116,7 +121,8 @@ module Unitsdb
|
|
|
116
121
|
collections = entity_type ? [entity_type.to_s] : %w[units prefixes]
|
|
117
122
|
|
|
118
123
|
collections.each do |collection_name|
|
|
119
|
-
next unless respond_to?(collection_name) && %w[units
|
|
124
|
+
next unless respond_to?(collection_name) && %w[units
|
|
125
|
+
prefixes].include?(collection_name)
|
|
120
126
|
|
|
121
127
|
collection = send(collection_name)
|
|
122
128
|
collection.each do |entity|
|
|
@@ -158,11 +164,16 @@ module Unitsdb
|
|
|
158
164
|
|
|
159
165
|
result = {
|
|
160
166
|
exact: [],
|
|
161
|
-
symbol_match: []
|
|
167
|
+
symbol_match: [],
|
|
162
168
|
}
|
|
163
169
|
|
|
164
170
|
# Define collections to search based on entity_type parameter
|
|
165
|
-
collections =
|
|
171
|
+
collections = if entity_type
|
|
172
|
+
[entity_type.to_s]
|
|
173
|
+
else
|
|
174
|
+
%w[units prefixes
|
|
175
|
+
quantities dimensions unit_systems]
|
|
176
|
+
end
|
|
166
177
|
|
|
167
178
|
collections.each do |collection_name|
|
|
168
179
|
next unless respond_to?(collection_name)
|
|
@@ -174,23 +185,25 @@ module Unitsdb
|
|
|
174
185
|
if %w[exact all].include?(match_type)
|
|
175
186
|
# Match by short
|
|
176
187
|
if entity.respond_to?(:short) && entity.short &&
|
|
177
|
-
|
|
188
|
+
entity.short.downcase == value.downcase
|
|
178
189
|
result[:exact] << {
|
|
179
190
|
entity: entity,
|
|
180
191
|
match_desc: "short_to_name",
|
|
181
|
-
details: "UnitsDB short '#{entity.short}' matches '#{value}'"
|
|
192
|
+
details: "UnitsDB short '#{entity.short}' matches '#{value}'",
|
|
182
193
|
}
|
|
183
194
|
next
|
|
184
195
|
end
|
|
185
196
|
|
|
186
197
|
# Match by names
|
|
187
198
|
if entity.respond_to?(:names) && entity.names
|
|
188
|
-
matching_name = entity.names.find
|
|
199
|
+
matching_name = entity.names.find do |name|
|
|
200
|
+
name.value.to_s.downcase == value.downcase
|
|
201
|
+
end
|
|
189
202
|
if matching_name
|
|
190
203
|
result[:exact] << {
|
|
191
204
|
entity: entity,
|
|
192
205
|
match_desc: "name_to_name",
|
|
193
|
-
details: "UnitsDB name '#{matching_name.value}' (#{matching_name.lang}) matches '#{value}'"
|
|
206
|
+
details: "UnitsDB name '#{matching_name.value}' (#{matching_name.lang}) matches '#{value}'",
|
|
194
207
|
}
|
|
195
208
|
next
|
|
196
209
|
end
|
|
@@ -199,7 +212,7 @@ module Unitsdb
|
|
|
199
212
|
|
|
200
213
|
# For symbol matches - only applicable to units and prefixes
|
|
201
214
|
if %w[symbol all].include?(match_type) &&
|
|
202
|
-
|
|
215
|
+
%w[units prefixes].include?(collection_name)
|
|
203
216
|
if collection_name == "units" && entity.respond_to?(:symbols) && entity.symbols
|
|
204
217
|
# Units can have multiple symbols
|
|
205
218
|
matching_symbol = entity.symbols.find do |sym|
|
|
@@ -211,7 +224,7 @@ module Unitsdb
|
|
|
211
224
|
result[:symbol_match] << {
|
|
212
225
|
entity: entity,
|
|
213
226
|
match_desc: "symbol_match",
|
|
214
|
-
details: "UnitsDB symbol '#{matching_symbol.ascii}' matches '#{value}'"
|
|
227
|
+
details: "UnitsDB symbol '#{matching_symbol.ascii}' matches '#{value}'",
|
|
215
228
|
}
|
|
216
229
|
end
|
|
217
230
|
elsif collection_name == "prefixes" && entity.respond_to?(:symbols) && entity.symbols
|
|
@@ -225,7 +238,7 @@ module Unitsdb
|
|
|
225
238
|
result[:symbol_match] << {
|
|
226
239
|
entity: entity,
|
|
227
240
|
match_desc: "symbol_match",
|
|
228
|
-
details: "UnitsDB symbol '#{matching_symbol.ascii}' matches '#{value}'"
|
|
241
|
+
details: "UnitsDB symbol '#{matching_symbol.ascii}' matches '#{value}'",
|
|
229
242
|
}
|
|
230
243
|
end
|
|
231
244
|
end
|
|
@@ -243,7 +256,7 @@ module Unitsdb
|
|
|
243
256
|
def validate_uniqueness
|
|
244
257
|
results = {
|
|
245
258
|
short: {},
|
|
246
|
-
id: {}
|
|
259
|
+
id: {},
|
|
247
260
|
}
|
|
248
261
|
|
|
249
262
|
# Validate short names for applicable collections
|
|
@@ -283,18 +296,24 @@ module Unitsdb
|
|
|
283
296
|
puts "Database directory path: #{db_path}"
|
|
284
297
|
|
|
285
298
|
# Check if the directory exists
|
|
286
|
-
|
|
299
|
+
unless Dir.exist?(db_path)
|
|
300
|
+
raise Errors::DatabaseNotFoundError,
|
|
301
|
+
"Database directory not found: #{db_path}"
|
|
302
|
+
end
|
|
287
303
|
|
|
288
304
|
# Define required files
|
|
289
|
-
required_files = %w[prefixes.yaml dimensions.yaml units.yaml
|
|
305
|
+
required_files = %w[prefixes.yaml dimensions.yaml units.yaml
|
|
306
|
+
quantities.yaml unit_systems.yaml]
|
|
290
307
|
yaml_files = required_files.map { |file| File.join(dir_path, file) }
|
|
291
308
|
|
|
292
309
|
# Check if all required files exist
|
|
293
|
-
missing_files = required_files.reject
|
|
310
|
+
missing_files = required_files.reject do |file|
|
|
311
|
+
File.exist?(File.join(dir_path, file))
|
|
312
|
+
end
|
|
294
313
|
|
|
295
314
|
if missing_files.any?
|
|
296
315
|
raise Errors::DatabaseFileNotFoundError,
|
|
297
|
-
"Missing required database files: #{missing_files.join(
|
|
316
|
+
"Missing required database files: #{missing_files.join(', ')}"
|
|
298
317
|
end
|
|
299
318
|
|
|
300
319
|
# Ensure we have path properly joined with filenames
|
|
@@ -316,15 +335,17 @@ module Unitsdb
|
|
|
316
335
|
|
|
317
336
|
# Load YAML files with better error handling
|
|
318
337
|
begin
|
|
319
|
-
prefixes_hash = YAML.
|
|
320
|
-
dimensions_hash = YAML.
|
|
321
|
-
units_hash = YAML.
|
|
322
|
-
quantities_hash = YAML.
|
|
323
|
-
unit_systems_hash = YAML.
|
|
338
|
+
prefixes_hash = YAML.safe_load_file(prefixes_yaml)
|
|
339
|
+
dimensions_hash = YAML.safe_load_file(dimensions_yaml)
|
|
340
|
+
units_hash = YAML.safe_load_file(units_yaml)
|
|
341
|
+
quantities_hash = YAML.safe_load_file(quantities_yaml)
|
|
342
|
+
unit_systems_hash = YAML.safe_load_file(unit_systems_yaml)
|
|
324
343
|
rescue Errno::ENOENT => e
|
|
325
|
-
raise Errors::DatabaseFileNotFoundError,
|
|
344
|
+
raise Errors::DatabaseFileNotFoundError,
|
|
345
|
+
"Failed to read database file: #{e.message}"
|
|
326
346
|
rescue Psych::SyntaxError => e
|
|
327
|
-
raise Errors::DatabaseFileInvalidError,
|
|
347
|
+
raise Errors::DatabaseFileInvalidError,
|
|
348
|
+
"Invalid YAML in database file: #{e.message}"
|
|
328
349
|
rescue StandardError => e
|
|
329
350
|
raise Errors::DatabaseLoadError, "Error loading database: #{e.message}"
|
|
330
351
|
end
|
|
@@ -339,7 +360,7 @@ module Unitsdb
|
|
|
339
360
|
|
|
340
361
|
if missing_schema.any?
|
|
341
362
|
raise Errors::DatabaseFileInvalidError,
|
|
342
|
-
"Missing schema_version in files: #{missing_schema.join(
|
|
363
|
+
"Missing schema_version in files: #{missing_schema.join(', ')}"
|
|
343
364
|
end
|
|
344
365
|
|
|
345
366
|
# Extract versions from each file
|
|
@@ -355,7 +376,7 @@ module Unitsdb
|
|
|
355
376
|
dimensions_version,
|
|
356
377
|
units_version,
|
|
357
378
|
quantities_version,
|
|
358
|
-
unit_systems_version
|
|
379
|
+
unit_systems_version,
|
|
359
380
|
]
|
|
360
381
|
|
|
361
382
|
unless versions.uniq.size == 1
|
|
@@ -364,9 +385,10 @@ module Unitsdb
|
|
|
364
385
|
"dimensions.yaml" => dimensions_version,
|
|
365
386
|
"units.yaml" => units_version,
|
|
366
387
|
"quantities.yaml" => quantities_version,
|
|
367
|
-
"unit_systems.yaml" => unit_systems_version
|
|
388
|
+
"unit_systems.yaml" => unit_systems_version,
|
|
368
389
|
}
|
|
369
|
-
raise Errors::VersionMismatchError,
|
|
390
|
+
raise Errors::VersionMismatchError,
|
|
391
|
+
"Version mismatch in database files: #{version_info.inspect}"
|
|
370
392
|
end
|
|
371
393
|
|
|
372
394
|
# Check if the version is supported
|
|
@@ -382,7 +404,7 @@ module Unitsdb
|
|
|
382
404
|
"dimensions" => dimensions_hash["dimensions"],
|
|
383
405
|
"units" => units_hash["units"],
|
|
384
406
|
"quantities" => quantities_hash["quantities"],
|
|
385
|
-
"unit_systems" => unit_systems_hash["unit_systems"]
|
|
407
|
+
"unit_systems" => unit_systems_hash["unit_systems"],
|
|
386
408
|
}.to_yaml
|
|
387
409
|
|
|
388
410
|
from_yaml(combined_yaml)
|
|
@@ -533,7 +555,8 @@ module Unitsdb
|
|
|
533
555
|
ref_type = "dimensions"
|
|
534
556
|
ref_path = "dimensions:index:#{index}:dimension_reference"
|
|
535
557
|
|
|
536
|
-
validate_reference(ref_id, ref_type, ref_path, registry, invalid_refs,
|
|
558
|
+
validate_reference(ref_id, ref_type, ref_path, registry, invalid_refs,
|
|
559
|
+
"dimensions")
|
|
537
560
|
end
|
|
538
561
|
end
|
|
539
562
|
|
|
@@ -545,7 +568,8 @@ module Unitsdb
|
|
|
545
568
|
ref_type = "unit_systems"
|
|
546
569
|
ref_path = "units:index:#{index}:unit_system_reference[#{idx}]"
|
|
547
570
|
|
|
548
|
-
validate_reference(ref_id, ref_type, ref_path, registry,
|
|
571
|
+
validate_reference(ref_id, ref_type, ref_path, registry,
|
|
572
|
+
invalid_refs, "units")
|
|
549
573
|
end
|
|
550
574
|
end
|
|
551
575
|
end
|
|
@@ -558,7 +582,8 @@ module Unitsdb
|
|
|
558
582
|
ref_type = "quantities"
|
|
559
583
|
ref_path = "units:index:#{index}:quantity_references[#{idx}]"
|
|
560
584
|
|
|
561
|
-
validate_reference(ref_id, ref_type, ref_path, registry,
|
|
585
|
+
validate_reference(ref_id, ref_type, ref_path, registry,
|
|
586
|
+
invalid_refs, "units")
|
|
562
587
|
end
|
|
563
588
|
end
|
|
564
589
|
end
|
|
@@ -575,7 +600,8 @@ module Unitsdb
|
|
|
575
600
|
ref_type = "units"
|
|
576
601
|
ref_path = "units:index:#{index}:root_units.#{idx}.unit_reference"
|
|
577
602
|
|
|
578
|
-
validate_reference(ref_id, ref_type, ref_path, registry,
|
|
603
|
+
validate_reference(ref_id, ref_type, ref_path, registry,
|
|
604
|
+
invalid_refs, "units")
|
|
579
605
|
|
|
580
606
|
# Check prefix reference if present
|
|
581
607
|
next unless root_unit.respond_to?(:prefix_reference) && root_unit.prefix_reference
|
|
@@ -584,12 +610,14 @@ module Unitsdb
|
|
|
584
610
|
ref_type = "prefixes"
|
|
585
611
|
ref_path = "units:index:#{index}:root_units.#{idx}.prefix_reference"
|
|
586
612
|
|
|
587
|
-
validate_reference(ref_id, ref_type, ref_path, registry,
|
|
613
|
+
validate_reference(ref_id, ref_type, ref_path, registry,
|
|
614
|
+
invalid_refs, "units")
|
|
588
615
|
end
|
|
589
616
|
end
|
|
590
617
|
end
|
|
591
618
|
|
|
592
|
-
def validate_reference(ref_id, ref_type, ref_path, registry, invalid_refs,
|
|
619
|
+
def validate_reference(ref_id, ref_type, ref_path, registry, invalid_refs,
|
|
620
|
+
file_type)
|
|
593
621
|
# Handle references that are objects with id and type (could be a hash or an object)
|
|
594
622
|
if ref_id.respond_to?(:id) && ref_id.respond_to?(:type)
|
|
595
623
|
id = ref_id.id
|
|
@@ -608,8 +636,12 @@ module Unitsdb
|
|
|
608
636
|
# 3. Try alternate ID formats for unit systems (e.g., SI_base vs si-base)
|
|
609
637
|
if !valid && type == "unitsml" && ref_type == "unit_systems" && registry.key?(ref_type) && (
|
|
610
638
|
registry[ref_type].keys.any? { |k| k.end_with?(":#{id}") } ||
|
|
611
|
-
registry[ref_type].keys.any?
|
|
612
|
-
|
|
639
|
+
registry[ref_type].keys.any? do |k|
|
|
640
|
+
k.end_with?(":SI_#{id.sub('si-', '')}")
|
|
641
|
+
end ||
|
|
642
|
+
registry[ref_type].keys.any? do |k|
|
|
643
|
+
k.end_with?(":non-SI_#{id.sub('nonsi-', '')}")
|
|
644
|
+
end
|
|
613
645
|
)
|
|
614
646
|
# Special handling for unit_systems between unitsml and nist types
|
|
615
647
|
valid = true
|
|
@@ -617,7 +649,8 @@ module Unitsdb
|
|
|
617
649
|
|
|
618
650
|
unless valid
|
|
619
651
|
invalid_refs[file_type] ||= {}
|
|
620
|
-
invalid_refs[file_type][ref_path] =
|
|
652
|
+
invalid_refs[file_type][ref_path] =
|
|
653
|
+
{ id: id, type: type, ref_type: ref_type }
|
|
621
654
|
end
|
|
622
655
|
# Handle references that are objects with id and type in a hash
|
|
623
656
|
elsif ref_id.is_a?(Hash) && ref_id.key?("id") && ref_id.key?("type")
|
|
@@ -637,8 +670,12 @@ module Unitsdb
|
|
|
637
670
|
# 3. Try alternate ID formats for unit systems (e.g., SI_base vs si-base)
|
|
638
671
|
if !valid && type == "unitsml" && ref_type == "unit_systems" && registry.key?(ref_type) && (
|
|
639
672
|
registry[ref_type].keys.any? { |k| k.end_with?(":#{id}") } ||
|
|
640
|
-
registry[ref_type].keys.any?
|
|
641
|
-
|
|
673
|
+
registry[ref_type].keys.any? do |k|
|
|
674
|
+
k.end_with?(":SI_#{id.sub('si-', '')}")
|
|
675
|
+
end ||
|
|
676
|
+
registry[ref_type].keys.any? do |k|
|
|
677
|
+
k.end_with?(":non-SI_#{id.sub('nonsi-', '')}")
|
|
678
|
+
end
|
|
642
679
|
)
|
|
643
680
|
# Special handling for unit_systems between unitsml and nist types
|
|
644
681
|
valid = true
|
|
@@ -646,7 +683,8 @@ module Unitsdb
|
|
|
646
683
|
|
|
647
684
|
unless valid
|
|
648
685
|
invalid_refs[file_type] ||= {}
|
|
649
|
-
invalid_refs[file_type][ref_path] =
|
|
686
|
+
invalid_refs[file_type][ref_path] =
|
|
687
|
+
{ id: id, type: type, ref_type: ref_type }
|
|
650
688
|
end
|
|
651
689
|
else
|
|
652
690
|
# Handle plain string references (legacy format)
|
data/lib/unitsdb/dimension.rb
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "identifier"
|
|
4
|
-
require_relative "dimension_details"
|
|
5
|
-
require_relative "quantity"
|
|
6
|
-
require_relative "localized_string"
|
|
7
3
|
# NISTd1:
|
|
8
4
|
# length:
|
|
9
5
|
# power: 1
|
|
@@ -45,5 +41,6 @@ module Unitsdb
|
|
|
45
41
|
attribute :plane_angle, DimensionDetails
|
|
46
42
|
attribute :short, :string
|
|
47
43
|
attribute :names, LocalizedString, collection: true
|
|
44
|
+
attribute :references, ExternalReference, collection: true
|
|
48
45
|
end
|
|
49
46
|
end
|
data/lib/unitsdb/dimensions.rb
CHANGED
data/lib/unitsdb/errors.rb
CHANGED
|
@@ -9,5 +9,12 @@ module Unitsdb
|
|
|
9
9
|
class DatabaseLoadError < DatabaseError; end
|
|
10
10
|
class VersionMismatchError < DatabaseError; end
|
|
11
11
|
class UnsupportedVersionError < DatabaseError; end
|
|
12
|
+
|
|
13
|
+
# CLI-specific errors
|
|
14
|
+
class CLIRuntimeError < StandardError; end
|
|
15
|
+
class InvalidParameterError < CLIRuntimeError; end
|
|
16
|
+
class FileNotFoundError < CLIRuntimeError; end
|
|
17
|
+
class ValidationError < CLIRuntimeError; end
|
|
18
|
+
class InvalidFormatError < CLIRuntimeError; end
|
|
12
19
|
end
|
|
13
20
|
end
|
data/lib/unitsdb/prefix.rb
CHANGED
data/lib/unitsdb/prefixes.rb
CHANGED
data/lib/unitsdb/quantities.rb
CHANGED
data/lib/unitsdb/quantity.rb
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "identifier"
|
|
4
|
-
require_relative "unit_reference"
|
|
5
|
-
require_relative "dimension_reference"
|
|
6
|
-
require_relative "external_reference"
|
|
7
|
-
require_relative "localized_string"
|
|
8
|
-
|
|
9
3
|
module Unitsdb
|
|
10
4
|
class Quantity < Lutaml::Model::Serializable
|
|
11
5
|
# model Config.model_for(:quantity)
|