unitsml 0.4.7 → 0.6.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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +8 -0
  3. data/.github/workflows/release.yml +7 -1
  4. data/.rubocop.yml +18 -0
  5. data/.rubocop_todo.yml +498 -0
  6. data/Gemfile +16 -11
  7. data/Rakefile +5 -3
  8. data/bin/console +4 -3
  9. data/docs/README.adoc +106 -4
  10. data/lib/unitsml/dimension.rb +49 -35
  11. data/lib/unitsml/errors/base_error.rb +8 -0
  12. data/lib/unitsml/errors/plurimath_load_error.rb +1 -1
  13. data/lib/unitsml/errors.rb +8 -0
  14. data/lib/unitsml/extender.rb +21 -16
  15. data/lib/unitsml/fenced.rb +97 -0
  16. data/lib/unitsml/fenced_numeric.rb +13 -0
  17. data/lib/unitsml/formula.rb +46 -33
  18. data/lib/unitsml/intermediate_exp_rules.rb +76 -0
  19. data/lib/unitsml/model/dimension.rb +4 -14
  20. data/lib/unitsml/model/dimension_quantities/quantity.rb +2 -0
  21. data/lib/unitsml/model/dimension_quantities.rb +17 -0
  22. data/lib/unitsml/model/prefix.rb +4 -8
  23. data/lib/unitsml/model/prefixes/name.rb +5 -4
  24. data/lib/unitsml/model/prefixes/symbol.rb +3 -2
  25. data/lib/unitsml/model/prefixes.rb +10 -0
  26. data/lib/unitsml/model/quantities/name.rb +4 -3
  27. data/lib/unitsml/model/quantities.rb +9 -0
  28. data/lib/unitsml/model/quantity.rb +5 -7
  29. data/lib/unitsml/model/unit.rb +4 -9
  30. data/lib/unitsml/model/units/enumerated_root_unit.rb +1 -0
  31. data/lib/unitsml/model/units/name.rb +4 -3
  32. data/lib/unitsml/model/units/root_units.rb +3 -2
  33. data/lib/unitsml/model/units/symbol.rb +2 -1
  34. data/lib/unitsml/model/units/system.rb +4 -3
  35. data/lib/unitsml/model/units.rb +13 -0
  36. data/lib/unitsml/model.rb +15 -0
  37. data/lib/unitsml/namespace.rb +8 -0
  38. data/lib/unitsml/number.rb +79 -0
  39. data/lib/unitsml/parse.rb +30 -38
  40. data/lib/unitsml/parser.rb +27 -13
  41. data/lib/unitsml/prefix.rb +17 -17
  42. data/lib/unitsml/sqrt.rb +3 -3
  43. data/lib/unitsml/transform.rb +143 -50
  44. data/lib/unitsml/unit.rb +67 -37
  45. data/lib/unitsml/unitsdb/dimension.rb +14 -20
  46. data/lib/unitsml/unitsdb/dimension_quantity.rb +2 -6
  47. data/lib/unitsml/unitsdb/dimensions.rb +3 -9
  48. data/lib/unitsml/unitsdb/prefix_reference.rb +23 -0
  49. data/lib/unitsml/unitsdb/prefixes.rb +17 -5
  50. data/lib/unitsml/unitsdb/quantities.rb +4 -4
  51. data/lib/unitsml/unitsdb/unit.rb +21 -0
  52. data/lib/unitsml/unitsdb/units.rb +19 -18
  53. data/lib/unitsml/unitsdb.rb +14 -5
  54. data/lib/unitsml/utility.rb +133 -103
  55. data/lib/unitsml/version.rb +3 -1
  56. data/lib/unitsml.rb +71 -35
  57. data/unitsdb/Gemfile +6 -0
  58. data/unitsdb/LICENSE.md +53 -0
  59. data/unitsdb/README.adoc +1253 -0
  60. data/unitsdb/RELEASE-NOTES.adoc +269 -0
  61. data/unitsdb/dimensions.yaml +1607 -602
  62. data/unitsdb/prefixes.yaml +842 -301
  63. data/unitsdb/quantities.yaml +3706 -2458
  64. data/unitsdb/scales.yaml +97 -0
  65. data/unitsdb/schemas/README.md +159 -0
  66. data/unitsdb/schemas/dimensions-schema.yaml +153 -0
  67. data/unitsdb/schemas/prefixes-schema.yaml +155 -0
  68. data/unitsdb/schemas/quantities-schema.yaml +117 -0
  69. data/unitsdb/schemas/scales-schema.yaml +106 -0
  70. data/unitsdb/schemas/unit_systems-schema.yaml +116 -0
  71. data/unitsdb/schemas/units-schema.yaml +215 -0
  72. data/unitsdb/spec/units_spec.rb +13 -10
  73. data/unitsdb/unit_systems.yaml +77 -15
  74. data/unitsdb/units.yaml +13517 -9974
  75. data/unitsdb/validate_schemas.rb +203 -0
  76. data/unitsml.gemspec +4 -1
  77. metadata +47 -7
  78. data/lib/unitsml/error.rb +0 -8
  79. data/unitsdb/docs/README.adoc +0 -12
  80. data/unitsdb/docs/navigation.adoc +0 -7
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "yaml"
4
+ require "json-schema"
5
+ require "json"
6
+ require "pathname"
7
+
8
+ class SchemaValidator
9
+ def initialize
10
+ @schemas_dir = Pathname.new("schemas")
11
+ @errors_found = false
12
+ end
13
+
14
+ def validate_all
15
+ puts "UnitsDB Schema Validation"
16
+ puts "=" * 50
17
+
18
+ # Define the mapping of YAML files to their schemas
19
+ file_schema_map = {
20
+ "units.yaml" => "units-schema.yaml",
21
+ "quantities.yaml" => "quantities-schema.yaml",
22
+ "scales.yaml" => "scales-schema.yaml",
23
+ "prefixes.yaml" => "prefixes-schema.yaml",
24
+ "unit_systems.yaml" => "unit_systems-schema.yaml",
25
+ "dimensions.yaml" => "dimensions-schema.yaml",
26
+ }
27
+
28
+ file_schema_map.each do |yaml_file, schema_file|
29
+ validate_file(yaml_file, schema_file)
30
+ end
31
+
32
+ puts "\n#{'=' * 50}"
33
+ if @errors_found
34
+ puts "❌ Validation completed with errors"
35
+ exit 1
36
+ else
37
+ puts "✅ All files passed validation"
38
+ exit 0
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def validate_file(yaml_file, schema_file)
45
+ puts "\nValidating #{yaml_file}..."
46
+
47
+ # Check if files exist
48
+ unless File.exist?(yaml_file)
49
+ puts "❌ YAML file not found: #{yaml_file}"
50
+ @errors_found = true
51
+ return
52
+ end
53
+
54
+ schema_path = @schemas_dir / schema_file
55
+ unless File.exist?(schema_path)
56
+ puts "❌ Schema file not found: #{schema_path}"
57
+ @errors_found = true
58
+ return
59
+ end
60
+
61
+ begin
62
+ # Load YAML data
63
+ yaml_data = YAML.load_file(yaml_file)
64
+
65
+ # Load schema (YAML schemas need to be converted to JSON for json-schema gem)
66
+ schema_yaml = YAML.load_file(schema_path)
67
+ schema_json = JSON.parse(schema_yaml.to_json)
68
+
69
+ # Validate
70
+ errors = JSON::Validator.fully_validate(schema_json, yaml_data,
71
+ errors_as_objects: true,
72
+ validate_schema: true)
73
+
74
+ if errors.empty?
75
+ puts "✅ #{yaml_file} - Valid"
76
+ else
77
+ puts "❌ #{yaml_file} - #{errors.length} error(s) found:"
78
+ @errors_found = true
79
+
80
+ errors.each_with_index do |error, index|
81
+ puts "\n Error #{index + 1}:"
82
+ puts " Path: #{error[:fragment] || 'root'}"
83
+ puts " Message: #{error[:message]}"
84
+
85
+ # Try to provide more context about the location
86
+ if error[:fragment] && !error[:fragment].empty?
87
+ path_parts = error[:fragment].split("/")
88
+ puts " Location: #{describe_path(path_parts, yaml_data)}"
89
+ end
90
+
91
+ # Show the failing value if available
92
+ if error[:failed_attribute] && error[:failed_attribute] != "schema"
93
+ puts " Failed validation: #{error[:failed_attribute]}"
94
+ end
95
+ end
96
+ end
97
+ rescue YAML::SyntaxError => e
98
+ puts "❌ YAML syntax error in #{yaml_file}:"
99
+ puts " Line #{e.line}: #{e.problem}"
100
+ @errors_found = true
101
+ rescue JSON::Schema::ValidationError => e
102
+ puts "❌ Schema validation error: #{e.message}"
103
+ @errors_found = true
104
+ rescue StandardError => e
105
+ puts "❌ Unexpected error validating #{yaml_file}: #{e.message}"
106
+ puts " #{e.class}: #{e.backtrace.first}"
107
+ @errors_found = true
108
+ end
109
+ end
110
+
111
+ def describe_path(path_parts, data)
112
+ current = data
113
+ description_parts = []
114
+
115
+ path_parts.each do |part|
116
+ next if part.empty? || part == "#"
117
+
118
+ if /^\d+$/.match?(part)
119
+ # Array index
120
+ index = part.to_i
121
+ if current.is_a?(Array) && current[index]
122
+ description_parts << "item #{index}"
123
+ current = current[index]
124
+ else
125
+ description_parts << "index #{index} (out of bounds)"
126
+ break
127
+ end
128
+ elsif current.is_a?(Hash) && current.key?(part)
129
+ # Object property
130
+ description_parts << "property '#{part}'"
131
+ current = current[part]
132
+ else
133
+ description_parts << "missing property '#{part}'"
134
+ break
135
+ end
136
+ end
137
+
138
+ description_parts.join(" -> ")
139
+ end
140
+ end
141
+
142
+ # Additional helper methods for detailed error reporting
143
+ class SchemaValidator
144
+ def self.check_dependencies
145
+ require "json-schema"
146
+ rescue LoadError
147
+ puts "❌ Missing required gem: json-schema"
148
+ puts " Install with: gem install json-schema"
149
+ exit 1
150
+ end
151
+
152
+ def self.run_with_options
153
+ check_dependencies
154
+
155
+ if ARGV.include?("--help") || ARGV.include?("-h")
156
+ show_help
157
+ exit 0
158
+ end
159
+
160
+ validator = new
161
+
162
+ if ARGV.include?("--verbose") || ARGV.include?("-v")
163
+ puts "Ruby version: #{RUBY_VERSION}"
164
+ puts "JSON Schema gem version: #{JSON::Schema::VERSION}"
165
+ puts "Working directory: #{Dir.pwd}"
166
+ puts ""
167
+ end
168
+
169
+ validator.validate_all
170
+ end
171
+
172
+ def self.show_help
173
+ puts <<~HELP
174
+ UnitsDB Schema Validator
175
+
176
+ Usage: ruby validate_schemas.rb [options]
177
+
178
+ Options:
179
+ -h, --help Show this help message
180
+ -v, --verbose Show additional information
181
+
182
+ This script validates all YAML files in the UnitsDB repository
183
+ against their corresponding JSON schemas in the schemas/ directory.
184
+
185
+ Files validated:
186
+ - units.yaml
187
+ - quantities.yaml
188
+ - scales.yaml
189
+ - prefixes.yaml
190
+ - unit_systems.yaml
191
+ - dimensions.yaml
192
+
193
+ Exit codes:
194
+ 0 - All files passed validation
195
+ 1 - Validation errors found or script error
196
+ HELP
197
+ end
198
+ end
199
+
200
+ # Run the validator if this script is executed directly
201
+ if __FILE__ == $0
202
+ SchemaValidator.run_with_options
203
+ end
data/unitsml.gemspec CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'lib/unitsml/version'
2
4
 
3
5
  Gem::Specification.new do |spec|
@@ -28,7 +30,8 @@ Gem::Specification.new do |spec|
28
30
  spec.require_paths = ['lib', 'unitsdb/**/*.yaml']
29
31
 
30
32
  spec.add_dependency 'htmlentities'
33
+ spec.add_dependency 'lutaml-model', '~> 0.8.0'
31
34
  spec.add_dependency 'mml'
32
35
  spec.add_dependency 'parslet'
33
- spec.add_dependency 'unitsdb', '~>1.0'
36
+ spec.add_dependency 'unitsdb', '~> 2.0'
34
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unitsml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.7
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-05-21 00:00:00.000000000 Z
11
+ date: 2026-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: htmlentities
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: lutaml-model
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.8.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.8.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: mml
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +72,14 @@ dependencies:
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: '1.0'
75
+ version: '2.0'
62
76
  type: :runtime
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: '1.0'
82
+ version: '2.0'
69
83
  description: Library to work with UnitsML in Ruby
70
84
  email:
71
85
  - open.source@ribose.com
@@ -80,6 +94,8 @@ files:
80
94
  - ".gitignore"
81
95
  - ".gitmodules"
82
96
  - ".rspec"
97
+ - ".rubocop.yml"
98
+ - ".rubocop_todo.yml"
83
99
  - Gemfile
84
100
  - LICENSE.md
85
101
  - Rakefile
@@ -90,11 +106,17 @@ files:
90
106
  - docs/navigation.adoc
91
107
  - lib/unitsml.rb
92
108
  - lib/unitsml/dimension.rb
93
- - lib/unitsml/error.rb
109
+ - lib/unitsml/errors.rb
110
+ - lib/unitsml/errors/base_error.rb
94
111
  - lib/unitsml/errors/plurimath_load_error.rb
95
112
  - lib/unitsml/extender.rb
113
+ - lib/unitsml/fenced.rb
114
+ - lib/unitsml/fenced_numeric.rb
96
115
  - lib/unitsml/formula.rb
116
+ - lib/unitsml/intermediate_exp_rules.rb
117
+ - lib/unitsml/model.rb
97
118
  - lib/unitsml/model/dimension.rb
119
+ - lib/unitsml/model/dimension_quantities.rb
98
120
  - lib/unitsml/model/dimension_quantities/amount_of_substance.rb
99
121
  - lib/unitsml/model/dimension_quantities/electric_current.rb
100
122
  - lib/unitsml/model/dimension_quantities/length.rb
@@ -105,16 +127,21 @@ files:
105
127
  - lib/unitsml/model/dimension_quantities/thermodynamic_temperature.rb
106
128
  - lib/unitsml/model/dimension_quantities/time.rb
107
129
  - lib/unitsml/model/prefix.rb
130
+ - lib/unitsml/model/prefixes.rb
108
131
  - lib/unitsml/model/prefixes/name.rb
109
132
  - lib/unitsml/model/prefixes/symbol.rb
133
+ - lib/unitsml/model/quantities.rb
110
134
  - lib/unitsml/model/quantities/name.rb
111
135
  - lib/unitsml/model/quantity.rb
112
136
  - lib/unitsml/model/unit.rb
137
+ - lib/unitsml/model/units.rb
113
138
  - lib/unitsml/model/units/enumerated_root_unit.rb
114
139
  - lib/unitsml/model/units/name.rb
115
140
  - lib/unitsml/model/units/root_units.rb
116
141
  - lib/unitsml/model/units/symbol.rb
117
142
  - lib/unitsml/model/units/system.rb
143
+ - lib/unitsml/namespace.rb
144
+ - lib/unitsml/number.rb
118
145
  - lib/unitsml/parse.rb
119
146
  - lib/unitsml/parser.rb
120
147
  - lib/unitsml/prefix.rb
@@ -125,19 +152,32 @@ files:
125
152
  - lib/unitsml/unitsdb/dimension.rb
126
153
  - lib/unitsml/unitsdb/dimension_quantity.rb
127
154
  - lib/unitsml/unitsdb/dimensions.rb
155
+ - lib/unitsml/unitsdb/prefix_reference.rb
128
156
  - lib/unitsml/unitsdb/prefixes.rb
129
157
  - lib/unitsml/unitsdb/quantities.rb
158
+ - lib/unitsml/unitsdb/unit.rb
130
159
  - lib/unitsml/unitsdb/units.rb
131
160
  - lib/unitsml/utility.rb
132
161
  - lib/unitsml/version.rb
162
+ - unitsdb/Gemfile
163
+ - unitsdb/LICENSE.md
164
+ - unitsdb/README.adoc
165
+ - unitsdb/RELEASE-NOTES.adoc
133
166
  - unitsdb/dimensions.yaml
134
- - unitsdb/docs/README.adoc
135
- - unitsdb/docs/navigation.adoc
136
167
  - unitsdb/prefixes.yaml
137
168
  - unitsdb/quantities.yaml
169
+ - unitsdb/scales.yaml
170
+ - unitsdb/schemas/README.md
171
+ - unitsdb/schemas/dimensions-schema.yaml
172
+ - unitsdb/schemas/prefixes-schema.yaml
173
+ - unitsdb/schemas/quantities-schema.yaml
174
+ - unitsdb/schemas/scales-schema.yaml
175
+ - unitsdb/schemas/unit_systems-schema.yaml
176
+ - unitsdb/schemas/units-schema.yaml
138
177
  - unitsdb/spec/units_spec.rb
139
178
  - unitsdb/unit_systems.yaml
140
179
  - unitsdb/units.yaml
180
+ - unitsdb/validate_schemas.rb
141
181
  - unitsml.gemspec
142
182
  homepage: https://github.com/unitsml/unitsml-ruby
143
183
  licenses:
data/lib/unitsml/error.rb DELETED
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Unitsml
4
- class Error < StandardError
5
- end
6
- end
7
-
8
- require_relative "errors/plurimath_load_error"
@@ -1,12 +0,0 @@
1
- = UnitsDB
2
-
3
- This data repository is used in conjunction with UnitsML.
4
-
5
- Sources include:
6
-
7
- * https://www.bipm.org/en/publications/si-brochure/[BIPM SI Brochure]
8
- * https://www.nist.gov/pml/special-publication-811[NIST SP 811]
9
- * ISO 80000 series
10
- * (in some cases, "Encyclopaedia of Scientific Units, Weights and Measures, Their SI Equivalences and Origins" by François Cardarelli, is consulted)
11
-
12
- NOTE: Conversion factors here are not updated with the revised SI.
@@ -1,7 +0,0 @@
1
- ---
2
- items:
3
- - title: README
4
- path: README/
5
- ---
6
-
7
- = Navigation