scjson 0.3.3 → 0.3.5

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.
@@ -7,5 +7,5 @@
7
7
  # Licensed under the BSD 1-Clause License.
8
8
 
9
9
  module Scjson
10
- VERSION = '0.1.4'
10
+ VERSION = '0.3.5'
11
11
  end
data/lib/scjson.rb CHANGED
@@ -7,9 +7,16 @@
7
7
  # Licensed under the BSD 1-Clause License.
8
8
 
9
9
  require 'json'
10
- require 'nokogiri'
10
+ begin
11
+ require 'nokogiri'
12
+ NOKOGIRI_AVAILABLE = true
13
+ rescue LoadError
14
+ NOKOGIRI_AVAILABLE = false
15
+ end
16
+ require 'shellwords'
11
17
 
12
18
  require_relative 'scjson/version'
19
+ require_relative 'scjson/types'
13
20
 
14
21
  # Canonical SCXML <-> scjson conversion for the Ruby agent.
15
22
  module Scjson
@@ -45,14 +52,41 @@ module Scjson
45
52
  # @param [Boolean] omit_empty Remove empty containers when true.
46
53
  # @return [String] Canonical scjson output.
47
54
  def xml_to_json(xml_str, omit_empty = true)
48
- doc = Nokogiri::XML(xml_str) { |cfg| cfg.strict.nonet }
49
- root = locate_root(doc)
50
- raise ArgumentError, 'Document missing <scxml> root element' unless root
51
-
52
- map = element_to_hash(root)
53
- collapse_whitespace(map)
54
- remove_empty(map) if omit_empty
55
- JSON.pretty_generate(map)
55
+ if NOKOGIRI_AVAILABLE
56
+ doc = Nokogiri::XML(xml_str) { |cfg| cfg.strict.nonet }
57
+ root = locate_root(doc)
58
+ raise ArgumentError, 'Document missing <scxml> root element' unless root
59
+
60
+ map = element_to_hash(root)
61
+ collapse_whitespace(map)
62
+ remove_empty(map) if omit_empty
63
+ return JSON.pretty_generate(map)
64
+ end
65
+ # Fallback: use Python CLI converter when Nokogiri is unavailable.
66
+ begin
67
+ require 'tmpdir'
68
+ Dir.mktmpdir('scjson-rb-xml2json') do |dir|
69
+ in_path = File.join(dir, 'in.scxml')
70
+ out_path = File.join(dir, 'out.scjson')
71
+ File.write(in_path, xml_str)
72
+ py_candidates = [ENV['PYTHON'], 'python3', 'python'].compact.uniq
73
+ ok = false
74
+ py_candidates.each do |py|
75
+ # Try package entrypoint; add repo-local 'py' to PYTHONPATH for import
76
+ repo_py = File.expand_path('../../py', __dir__)
77
+ env = {}
78
+ current_pp = ENV['PYTHONPATH']
79
+ env['PYTHONPATH'] = current_pp ? (repo_py + File::PATH_SEPARATOR + current_pp) : repo_py
80
+ cmd = [py, '-m', 'scjson.cli', 'json', in_path, '-o', out_path]
81
+ ok = system(env, *cmd, out: File::NULL, err: File::NULL) && File.file?(out_path)
82
+ break if ok
83
+ end
84
+ raise 'python converter failed' unless ok
85
+ return File.read(out_path)
86
+ end
87
+ rescue StandardError => e
88
+ raise LoadError, "SCXML->JSON conversion unavailable: Nokogiri missing and external converter failed (#{e})"
89
+ end
56
90
  end
57
91
 
58
92
  ##
@@ -61,13 +95,39 @@ module Scjson
61
95
  # @param [String] json_str Canonical scjson input.
62
96
  # @return [String] XML document encoded as UTF-8.
63
97
  def json_to_xml(json_str)
64
- data = JSON.parse(json_str)
65
- remove_empty(data)
66
- doc = Nokogiri::XML::Document.new
67
- doc.encoding = 'utf-8'
68
- root = build_element(doc, 'scxml', data)
69
- doc.root = root
70
- doc.to_xml
98
+ if NOKOGIRI_AVAILABLE
99
+ data = JSON.parse(json_str)
100
+ remove_empty(data)
101
+ doc = Nokogiri::XML::Document.new
102
+ doc.encoding = 'utf-8'
103
+ root = build_element(doc, 'scxml', data)
104
+ doc.root = root
105
+ return doc.to_xml
106
+ end
107
+ # Fallback: use Python CLI converter when Nokogiri is unavailable.
108
+ begin
109
+ require 'tmpdir'
110
+ Dir.mktmpdir('scjson-rb-json2xml') do |dir|
111
+ in_path = File.join(dir, 'in.scjson')
112
+ out_path = File.join(dir, 'out.scxml')
113
+ File.write(in_path, json_str)
114
+ py_candidates = [ENV['PYTHON'], 'python3', 'python'].compact.uniq
115
+ ok = false
116
+ py_candidates.each do |py|
117
+ repo_py = File.expand_path('../../py', __dir__)
118
+ env = {}
119
+ current_pp = ENV['PYTHONPATH']
120
+ env['PYTHONPATH'] = current_pp ? (repo_py + File::PATH_SEPARATOR + current_pp) : repo_py
121
+ cmd = [py, '-m', 'scjson.cli', 'xml', in_path, '-o', out_path]
122
+ ok = system(env, *cmd, out: File::NULL, err: File::NULL) && File.file?(out_path)
123
+ break if ok
124
+ end
125
+ raise 'python converter failed' unless ok
126
+ return File.read(out_path)
127
+ end
128
+ rescue StandardError => e
129
+ raise LoadError, "JSON->SCXML conversion unavailable: Nokogiri missing and external converter failed (#{e})"
130
+ end
71
131
  end
72
132
 
73
133
  # ----------------------------
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scjson
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Softoboros Technology Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-10-01 00:00:00.000000000 Z
11
+ date: 2025-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -24,7 +24,9 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
- description:
27
+ description: 'scjson: SCXML ↔ JSON converter, validator, and execution trace interface.
28
+ Provides CLI tools for conversion, validation, and emitting deterministic traces
29
+ compatible with SCION semantics.'
28
30
  email:
29
31
  - info@softoboros.com
30
32
  executables:
@@ -32,14 +34,25 @@ executables:
32
34
  extensions: []
33
35
  extra_rdoc_files: []
34
36
  files:
37
+ - LEGAL.md
38
+ - LICENSE
39
+ - README.md
35
40
  - bin/scjson
36
41
  - lib/scjson.rb
37
42
  - lib/scjson/cli.rb
43
+ - lib/scjson/engine.rb
44
+ - lib/scjson/engine/context.rb
45
+ - lib/scjson/types.rb
38
46
  - lib/scjson/version.rb
39
- homepage:
47
+ homepage: https://github.com/SoftOboros/scjson
40
48
  licenses:
41
49
  - BSD-1-Clause
42
- metadata: {}
50
+ metadata:
51
+ source_code_uri: https://github.com/SoftOboros/scjson
52
+ documentation_uri: https://github.com/SoftOboros/scjson/tree/main/docs
53
+ changelog_uri: https://github.com/SoftOboros/scjson/releases
54
+ homepage_uri: https://github.com/SoftOboros/scjson
55
+ keywords: scxml,statecharts,state-machine,scjson,scml,execution
43
56
  post_install_message:
44
57
  rdoc_options: []
45
58
  require_paths:
@@ -58,5 +71,5 @@ requirements: []
58
71
  rubygems_version: 3.4.19
59
72
  signing_key:
60
73
  specification_version: 4
61
- summary: SCXML <-> scjson converter and validator
74
+ summary: SCXML/SCML execution, SCXML <-> scjson converter and validator
62
75
  test_files: []