unitsdb 2.1.0 → 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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +8 -1
  3. data/.gitignore +2 -0
  4. data/.gitmodules +4 -3
  5. data/.rubocop.yml +13 -8
  6. data/.rubocop_todo.yml +247 -53
  7. data/CLAUDE.md +55 -0
  8. data/Gemfile +5 -1
  9. data/README.adoc +385 -12
  10. data/data/dimensions.yaml +1864 -0
  11. data/data/prefixes.yaml +874 -0
  12. data/data/quantities.yaml +3715 -0
  13. data/data/scales.yaml +97 -0
  14. data/data/schemas/dimensions-schema.yaml +153 -0
  15. data/data/schemas/prefixes-schema.yaml +155 -0
  16. data/data/schemas/quantities-schema.yaml +117 -0
  17. data/data/schemas/scales-schema.yaml +106 -0
  18. data/data/schemas/unit_systems-schema.yaml +116 -0
  19. data/data/schemas/units-schema.yaml +215 -0
  20. data/data/unit_systems.yaml +78 -0
  21. data/data/units.yaml +14052 -0
  22. data/exe/unitsdb +7 -1
  23. data/lib/unitsdb/cli.rb +47 -13
  24. data/lib/unitsdb/commands/_modify.rb +41 -5
  25. data/lib/unitsdb/commands/base.rb +10 -32
  26. data/lib/unitsdb/commands/check_si/si_formatter.rb +488 -0
  27. data/lib/unitsdb/commands/check_si/si_matcher.rb +487 -0
  28. data/lib/unitsdb/commands/check_si/si_ttl_parser.rb +103 -0
  29. data/lib/unitsdb/commands/check_si/si_updater.rb +254 -0
  30. data/lib/unitsdb/commands/check_si.rb +54 -35
  31. data/lib/unitsdb/commands/get.rb +11 -10
  32. data/lib/unitsdb/commands/normalize.rb +21 -7
  33. data/lib/unitsdb/commands/qudt/check.rb +150 -0
  34. data/lib/unitsdb/commands/qudt/formatter.rb +194 -0
  35. data/lib/unitsdb/commands/qudt/matcher.rb +746 -0
  36. data/lib/unitsdb/commands/qudt/ttl_parser.rb +403 -0
  37. data/lib/unitsdb/commands/qudt/update.rb +126 -0
  38. data/lib/unitsdb/commands/qudt/updater.rb +189 -0
  39. data/lib/unitsdb/commands/qudt.rb +82 -0
  40. data/lib/unitsdb/commands/release.rb +50 -86
  41. data/lib/unitsdb/commands/search.rb +12 -11
  42. data/lib/unitsdb/commands/ucum/check.rb +139 -0
  43. data/lib/unitsdb/commands/ucum/formatter.rb +142 -0
  44. data/lib/unitsdb/commands/ucum/matcher.rb +315 -0
  45. data/lib/unitsdb/commands/ucum/update.rb +85 -0
  46. data/lib/unitsdb/commands/ucum/updater.rb +132 -0
  47. data/lib/unitsdb/commands/ucum/xml_parser.rb +32 -0
  48. data/lib/unitsdb/commands/ucum.rb +83 -0
  49. data/lib/unitsdb/commands/validate/identifiers.rb +3 -3
  50. data/lib/unitsdb/commands/validate/qudt_references.rb +111 -0
  51. data/lib/unitsdb/commands/validate/references.rb +37 -18
  52. data/lib/unitsdb/commands/validate/si_references.rb +3 -11
  53. data/lib/unitsdb/commands/validate/ucum_references.rb +105 -0
  54. data/lib/unitsdb/commands/validate.rb +67 -11
  55. data/lib/unitsdb/commands.rb +20 -0
  56. data/lib/unitsdb/database.rb +91 -52
  57. data/lib/unitsdb/dimension.rb +1 -4
  58. data/lib/unitsdb/dimension_details.rb +0 -1
  59. data/lib/unitsdb/dimensions.rb +1 -2
  60. data/lib/unitsdb/errors.rb +7 -0
  61. data/lib/unitsdb/prefix.rb +0 -4
  62. data/lib/unitsdb/prefix_reference.rb +0 -2
  63. data/lib/unitsdb/prefixes.rb +1 -1
  64. data/lib/unitsdb/quantities.rb +1 -2
  65. data/lib/unitsdb/quantity.rb +0 -6
  66. data/lib/unitsdb/qudt.rb +100 -0
  67. data/lib/unitsdb/root_unit_reference.rb +0 -3
  68. data/lib/unitsdb/scale.rb +0 -4
  69. data/lib/unitsdb/scale_reference.rb +0 -2
  70. data/lib/unitsdb/scales.rb +1 -2
  71. data/lib/unitsdb/si_derived_base.rb +0 -2
  72. data/lib/unitsdb/ucum.rb +202 -0
  73. data/lib/unitsdb/unit.rb +0 -10
  74. data/lib/unitsdb/unit_reference.rb +0 -2
  75. data/lib/unitsdb/unit_system.rb +1 -3
  76. data/lib/unitsdb/unit_system_reference.rb +0 -2
  77. data/lib/unitsdb/unit_systems.rb +1 -2
  78. data/lib/unitsdb/units.rb +1 -2
  79. data/lib/unitsdb/utils.rb +32 -21
  80. data/lib/unitsdb/version.rb +5 -1
  81. data/lib/unitsdb.rb +62 -14
  82. data/unitsdb.gemspec +6 -5
  83. metadata +60 -13
  84. data/lib/unitsdb/commands/si_formatter.rb +0 -485
  85. data/lib/unitsdb/commands/si_matcher.rb +0 -470
  86. data/lib/unitsdb/commands/si_ttl_parser.rb +0 -100
  87. data/lib/unitsdb/commands/si_updater.rb +0 -212
data/exe/unitsdb CHANGED
@@ -4,4 +4,10 @@
4
4
  require "unitsdb"
5
5
  require "unitsdb/cli"
6
6
 
7
- Unitsdb::CLI.start(ARGV)
7
+ begin
8
+ Unitsdb::Cli.start(ARGV)
9
+ rescue SystemExit => e
10
+ # Only print if not already handled (exit code 0 = normal exit)
11
+ # Exit code 1 from our commands is already handled, don't duplicate
12
+ raise if e.status.zero?
13
+ end
data/lib/unitsdb/cli.rb CHANGED
@@ -1,21 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "thor"
4
- require_relative "commands/validate"
5
- require_relative "commands/_modify"
6
4
  require "fileutils"
7
5
 
8
6
  module Unitsdb
9
- class CLI < Thor
7
+ class Cli < Thor
8
+ # Enable --trace globally for all subcommands
9
+ # When enabled, Thor shows full backtraces on error
10
+ class_option :trace, type: :boolean, default: false,
11
+ desc: "Show full backtrace on error"
12
+
10
13
  # Fix Thor deprecation warning
11
14
  def self.exit_on_failure?
12
15
  true
13
16
  end
14
17
 
18
+ desc "ucum SUBCOMMAND", "UCUM-related commands"
19
+ subcommand "ucum", Commands::UcumCommand
20
+
21
+ desc "qudt SUBCOMMAND", "QUDT-related commands"
22
+ subcommand "qudt", Commands::QudtCommand
23
+
15
24
  desc "_modify SUBCOMMAND", "Commands that modify the database"
16
25
  subcommand "_modify", Commands::ModifyCommand
17
26
 
18
- desc "validate SUBCOMMAND", "Validate database files for different conditions"
27
+ desc "validate SUBCOMMAND",
28
+ "Validate database files for different conditions"
19
29
  subcommand "validate", Commands::ValidateCommand
20
30
 
21
31
  desc "search QUERY", "Search for entities containing the given text"
@@ -31,8 +41,7 @@ module Unitsdb
31
41
  desc: "Path to UnitsDB database (required)"
32
42
 
33
43
  def search(query)
34
- require_relative "commands/search"
35
- Commands::Search.new(options).run(query)
44
+ run_command(Commands::Search, :run, query)
36
45
  end
37
46
 
38
47
  desc "get ID", "Get detailed information about an entity by ID"
@@ -43,11 +52,11 @@ module Unitsdb
43
52
  option :database, type: :string, required: true, aliases: "-d",
44
53
  desc: "Path to UnitsDB database (required)"
45
54
  def get(id)
46
- require_relative "commands/get"
47
- Commands::Get.new(options).get(id)
55
+ run_command(Commands::Get, :get, id)
48
56
  end
49
57
 
50
- desc "check_si", "Check and update SI digital framework references in UnitsDB"
58
+ desc "check_si",
59
+ "Check and update SI digital framework references in UnitsDB"
51
60
  option :entity_type, type: :string, aliases: "-e",
52
61
  desc: "Entity type to check (units, quantities, or prefixes). If not specified, all types are checked"
53
62
  option :ttl_dir, type: :string, required: true, aliases: "-t",
@@ -62,8 +71,7 @@ module Unitsdb
62
71
  desc: "Path to UnitsDB database (required)"
63
72
 
64
73
  def check_si
65
- require_relative "commands/check_si"
66
- Commands::CheckSi.new(options).run
74
+ run_command(Commands::CheckSiCommand, :run)
67
75
  end
68
76
 
69
77
  desc "release", "Create release files (unified YAML and/or ZIP archive)"
@@ -71,11 +79,37 @@ module Unitsdb
71
79
  desc: "Output format: 'yaml' (single file), 'zip' (archive), or 'all' (both)"
72
80
  option :output_dir, type: :string, default: ".", aliases: "-o",
73
81
  desc: "Directory to output release files"
82
+ option :version, type: :string, aliases: "-v", required: true,
83
+ desc: "Version number for the release (x.y.z)"
74
84
  option :database, type: :string, required: true, aliases: "-d",
75
85
  desc: "Path to UnitsDB database (required)"
76
86
  def release
77
- require_relative "commands/release"
78
- Commands::Release.new(options).run
87
+ run_command(Commands::Release, :run)
88
+ end
89
+
90
+ private
91
+
92
+ def run_command(command_class, method, *args)
93
+ command = command_class.new(options)
94
+ command.send(method, *args)
95
+ rescue Unitsdb::Errors::CLIRuntimeError => e
96
+ handle_cli_error(e)
97
+ rescue StandardError => e
98
+ handle_error(e)
99
+ end
100
+
101
+ def handle_cli_error(error)
102
+ raise error if debugging?
103
+
104
+ warn "Error: #{error.message}"
105
+ exit 1
106
+ end
107
+
108
+ def handle_error(error)
109
+ raise error if debugging?
110
+
111
+ warn "Error: #{error.message}"
112
+ exit 1
79
113
  end
80
114
  end
81
115
  end
@@ -5,17 +5,53 @@ require "thor"
5
5
  module Unitsdb
6
6
  module Commands
7
7
  class ModifyCommand < Thor
8
- desc "normalize [INPUT] [OUTPUT]", "Normalize a YAML file or all YAML files with --all"
9
- method_option :sort, type: :string, default: "short",
10
- desc: "Sort units by: 'short' (name), 'nist' (ID), 'unitsml' (ID), or 'none'"
8
+ # Inherit trace option from parent CLI
9
+ class_option :trace, type: :boolean, default: false,
10
+ desc: "Show full backtrace on error"
11
+
12
+ desc "normalize INPUT OUTPUT",
13
+ "Normalize a YAML file or all YAML files with --all"
14
+ method_option :sort, type: :string,
15
+ default: "nist",
16
+ enum: ["short", "nist", "unitsml", "none"],
17
+ aliases: "-s",
18
+ desc: "Sort units by: 'short' (name), 'nist' (ID, default), 'unitsml' (ID), or 'none'"
11
19
  method_option :database, type: :string, required: true, aliases: "-d",
12
20
  desc: "Path to UnitsDB database (required)"
13
21
  method_option :all, type: :boolean, default: false, aliases: "-a",
14
22
  desc: "Process all YAML files in the repository"
15
23
 
16
24
  def normalize(input = nil, output = nil)
17
- require_relative "normalize"
18
- Normalize.new(options).run(input, output)
25
+ run_command(Normalize, options, input, output)
26
+ rescue Unitsdb::Errors::CLIRuntimeError => e
27
+ handle_cli_error(e)
28
+ rescue StandardError => e
29
+ handle_error(e)
30
+ end
31
+
32
+ private
33
+
34
+ def run_command(command_class, options, *args)
35
+ command = command_class.new(options)
36
+ command.run(*args)
37
+ end
38
+
39
+ def handle_cli_error(error)
40
+ if options[:trace]
41
+ raise error
42
+ else
43
+ warn "Error: #{error.message}"
44
+ exit 1
45
+ end
46
+ end
47
+
48
+ def handle_error(error)
49
+ if options[:trace]
50
+ raise error
51
+ else
52
+ warn "Error: #{error.message}"
53
+ exit 1
54
+ end
19
55
  end
20
56
  end
21
57
  end
@@ -1,51 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "thor"
4
3
  require "yaml"
5
- require_relative "../utils"
6
- require_relative "../database"
4
+ require "fileutils"
7
5
 
8
6
  module Unitsdb
9
7
  module Commands
10
8
  class Base
11
9
  def initialize(options = {})
12
10
  @options = options
11
+ puts "Database directory path: #{@options[:database]}" if @options[:database]
13
12
  end
14
13
 
15
14
  protected
16
15
 
17
- def yaml_files(input = nil, opts = nil)
18
- options_to_use = opts || @options
19
-
20
- if options_to_use[:all]
21
- Unitsdb::Utils::DEFAULT_YAML_FILES.map { |f| File.join(options_to_use[:database], f) }
22
- elsif input
23
- [input]
24
- else
25
- puts "Error: INPUT file is required when not using --all"
26
- exit(1)
16
+ def load_database(path = nil)
17
+ path ||= @options[:database]
18
+ unless path
19
+ raise Unitsdb::Errors::DatabaseError,
20
+ "Database path not specified"
27
21
  end
28
- end
29
-
30
- def load_database(database_path = nil)
31
- path = database_path || @options[:database]
32
-
33
- raise Unitsdb::Errors::DatabaseError, "Database path must be specified using the --database option" if path.nil?
34
22
 
35
23
  Unitsdb::Database.from_db(path)
36
- rescue Unitsdb::Errors::DatabaseError => e
37
- puts "Error: #{e.message}"
38
- exit(1)
39
- end
40
-
41
- def load_yaml(file_path)
42
- return nil unless File.exist?(file_path)
43
-
44
- YAML.safe_load(File.read(file_path))
45
- end
46
-
47
- def file_type(file_path)
48
- File.basename(file_path, ".yaml")
24
+ rescue StandardError => e
25
+ raise Unitsdb::Errors::DatabaseError,
26
+ "Failed to load database: #{e.message}"
49
27
  end
50
28
  end
51
29
  end