microfsm 0.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f8380343e775bb2c143ccb457454ab729544226984831170d68d674faa5b674f
4
+ data.tar.gz: 3b9cc48b46baac3f500309345312302ce79069b568043979efc220a1adf98ae2
5
+ SHA512:
6
+ metadata.gz: 9ff4030bcdeb6a31ae300a1ec575aa252fb9f08267e8482eb361bd26884eb2b307bf30d397bfdd6e6a57bfb70f72900f593bf53f579e029dcbad5802d92ee561
7
+ data.tar.gz: fe18e71eca3810d8e0a2b862fc37cb580854b11162116fd27c78933654cb46b93494ea95431dfd9bdfcedf0e0b0423c9340e58fbf1166c792a02c79792dc0028
@@ -0,0 +1,19 @@
1
+ inherit_from:
2
+ - ~/configs/.rubocop.yml
3
+
4
+ AllCops:
5
+ Include:
6
+ - 'lib/**/*.rb'
7
+
8
+ Exclude:
9
+ - 'bin/**/*'
10
+ - 'test/**/*'
11
+ SuggestExtensions: false
12
+
13
+ Layout/AccessModifierIndentation:
14
+ Enabled: false
15
+ Layout/EmptyLinesAroundAccessModifier:
16
+ Enabled: false
17
+
18
+ Metrics/AbcSize:
19
+ Enabled: false
@@ -0,0 +1 @@
1
+ rails-6.1
@@ -0,0 +1 @@
1
+ ruby-2.7.2
data/.watchr ADDED
@@ -0,0 +1,57 @@
1
+ HH = '#' * 22 unless defined?(HH)
2
+ H = '#' * 5 unless defined?(H)
3
+
4
+ def usage
5
+ puts <<-EOS
6
+ Ctrl-\\ or ctrl-4 Running all tests
7
+ Ctrl-C Exit
8
+ EOS
9
+ end
10
+
11
+ def run(cmd)
12
+ puts "#{HH} #{Time.now} #{HH}"
13
+ puts "#{H} #{cmd}"
14
+ system "/usr/bin/time --format '#{HH} Elapsed time %E' #{cmd}"
15
+ end
16
+
17
+ def run_it(type, file)
18
+ case type
19
+ when 'test'; run %Q(ruby -I"lib:test" -r rubygems #{file})
20
+ else; puts "#{H} unknown type: #{type}, file: #{file}"
21
+ end
22
+ end
23
+
24
+ def run_all_tests
25
+ puts "\n#{HH} Running all tests #{HH}\n"
26
+ %w[test].each { |dir| run "rake #{dir}" if File.exist?(dir) }
27
+ end
28
+
29
+ def run_matching_files(base)
30
+ base = base.split('_').first
31
+ %w[test spec].each { |type|
32
+ files = Dir["#{type}/**/*.rb"].select { |file| file =~ /#{base}_.*\.rb/ }
33
+ run_it type, files.join(' ') unless files.empty?
34
+ }
35
+ end
36
+
37
+ %w[test spec].each { |type|
38
+ watch("#{type}/#{type}_helper\.rb") { run_all_tests }
39
+ watch("#{type}/.*/*_#{type}\.rb") { |match| run_it type, match[0] }
40
+ watch("#{type}/data/(.*)\.rb") { |match|
41
+ m1 = match[1]
42
+ run_matching_files("#{type}/#{m1}/#{m1}_#{type}.rb")
43
+ }
44
+ }
45
+ %w[rb erb haml slim].each { |type|
46
+ # watch("app/.*/(.*)\.#{type}") { |match|
47
+ watch(".*/(.*)\.#{type}") { |match|
48
+ p [11, match]
49
+ run_matching_files(match[1])
50
+ }
51
+ }
52
+
53
+ # Ctrl-\ or ctrl-4
54
+ Signal.trap('QUIT') { run_all_tests }
55
+ # Ctrl-C
56
+ Signal.trap('INT') { abort("Interrupted\n") }
57
+ usage
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'observr'
7
+ gem 'rubocop', require: false
8
+ gem 'simplecov', require: false
9
+ end
@@ -0,0 +1,53 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ microfsm (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.2)
10
+ docile (1.3.5)
11
+ minitest (5.14.3)
12
+ observr (1.0.5)
13
+ parallel (1.20.1)
14
+ parser (3.0.0.0)
15
+ ast (~> 2.4.1)
16
+ rainbow (3.0.0)
17
+ rake (13.0.3)
18
+ regexp_parser (2.0.3)
19
+ rexml (3.2.4)
20
+ rubocop (1.8.1)
21
+ parallel (~> 1.10)
22
+ parser (>= 3.0.0.0)
23
+ rainbow (>= 2.2.2, < 4.0)
24
+ regexp_parser (>= 1.8, < 3.0)
25
+ rexml
26
+ rubocop-ast (>= 1.2.0, < 2.0)
27
+ ruby-progressbar (~> 1.7)
28
+ unicode-display_width (>= 1.4.0, < 3.0)
29
+ rubocop-ast (1.4.1)
30
+ parser (>= 2.7.1.5)
31
+ ruby-progressbar (1.11.0)
32
+ simplecov (0.21.2)
33
+ docile (~> 1.1)
34
+ simplecov-html (~> 0.11)
35
+ simplecov_json_formatter (~> 0.1)
36
+ simplecov-html (0.12.3)
37
+ simplecov_json_formatter (0.1.2)
38
+ unicode-display_width (2.0.0)
39
+
40
+ PLATFORMS
41
+ ruby
42
+
43
+ DEPENDENCIES
44
+ bundler
45
+ microfsm!
46
+ minitest
47
+ observr
48
+ rake
49
+ rubocop
50
+ simplecov
51
+
52
+ BUNDLED WITH
53
+ 2.1.4
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2021 Dittmar Krall
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,88 @@
1
+ # MicroFSM
2
+
3
+ MicroFSM implements a minimal/simple Finite-State Machine (FSM).
4
+ Transitions are triggered by events.
5
+ Actions for a transition can be added as callbacks.
6
+
7
+ Finite-State Machine are described elsewhere, e.g. Wikipedia.
8
+
9
+ Several FSM implementations are available for Ruby.
10
+ Please feel free to use any of them if they fit better to your work.
11
+
12
+ The MicroFSM code consists of less than 70 locs.
13
+ No magic, no niceties, just an implementation using Ruby hashes.
14
+
15
+ Check the examples directory for more information.
16
+
17
+
18
+ ## Installation
19
+
20
+ ~~~~
21
+ # Gemfile
22
+ gem "wysiwyg-rails"
23
+
24
+ $ bundle install.
25
+
26
+ # or manually
27
+
28
+ $ [sudo] gem install microfsm
29
+ ~~~~
30
+
31
+ ## Usage
32
+
33
+ ~~~~
34
+ require 'microfsm'
35
+
36
+ fsm = MicroFSM.new(:new) # Initial state.
37
+
38
+ # Define the possible transitions for each event.
39
+ fsm.when(:confirm, :new => :confirmed)
40
+ fsm.when(:ignore, :new => :ignored)
41
+ fsm.when(:reset, :confirmed => :new, :ignored => :new)
42
+
43
+ fsm.trigger(:confirm) #=> true
44
+ fsm.state #=> :confirmed
45
+
46
+ fsm.trigger(:ignore) #=> false
47
+ fsm.state #=> :confirmed
48
+
49
+ fsm.trigger(:reset) #=> true
50
+ fsm.state #=> :new
51
+
52
+ fsm.trigger(:ignore) #=> true
53
+ fsm.state #=> :ignored
54
+ ~~~~
55
+
56
+ You can also ask if an event will trigger a change in state. Following
57
+ the example above:
58
+
59
+ ~~~~
60
+ fsm.state #=> :ignored
61
+
62
+ fsm.trigger?(:ignore) #=> false
63
+ fsm.trigger?(:reset) #=> true
64
+
65
+ # And the state is preserved, because you were only asking.
66
+ fsm.state #=> :ignored
67
+ ~~~~
68
+
69
+
70
+ Finally, you can list possible events or states:
71
+
72
+ ~~~~
73
+ # All possible events
74
+ fsm.events #=> [:confirm, :ignore, :reset]
75
+
76
+ # All events triggerable from the current state
77
+ fsm.triggerable_events #=> [:confirm, :ignore]
78
+
79
+ # All possible states
80
+ fsm.states #=> [:new, :confirmed, :ignored]
81
+ ~~~~
82
+
83
+ Check the examples directory for more information.
84
+
85
+ ## Links
86
+
87
+ - [Wikipedia](https://en.wikipedia.org/wiki/Finite-state_machine)
88
+ - [micromachine](https://github.com/soveran/micromachine)
@@ -0,0 +1,10 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs.push 'test'
6
+ t.pattern = 'test/*_test.rb'
7
+ end
8
+
9
+ desc 'Default: run unit tests.'
10
+ task :default => :test
@@ -0,0 +1,21 @@
1
+ require 'microfsm'
2
+
3
+ # This example can be run with ruby -I lib/ ./examples/advanced.rb
4
+
5
+ fsm = MicroFSM.new(:pending)
6
+ proc = -> (event) { puts fsm.state.capitalize }
7
+ fsm.when(:confirm, :pending => :confirmed, &proc)
8
+ .when(:ignore, :pending => :ignored, &proc)
9
+ .when(:reset, :confirmed => :pending, :ignored => :pending, &proc)
10
+
11
+ puts "Should print Confirmed, Pending and Ignored:"
12
+ fsm.trigger(:confirm)
13
+ fsm.trigger(:ignore)
14
+ fsm.trigger(:reset)
15
+ fsm.trigger(:ignore)
16
+
17
+ puts "Should print all states: confirmed, ignored, pending"
18
+ puts fsm.states.join ", "
19
+
20
+ puts "Should print all events: confirm, ignore, reset"
21
+ puts fsm.events.join ", "
@@ -0,0 +1,26 @@
1
+ require 'microfsm'
2
+
3
+ # This example can be run with ruby -I lib/ ./examples/basic.rb
4
+
5
+ fsm = MicroFSM.new(:pending)
6
+ .when(:confirm, :pending => :confirmed)
7
+ .when(:ignore, :pending => :ignored)
8
+ .when(:reset, :confirmed => :pending, :ignored => :pending)
9
+
10
+ puts "Should print Confirmed, Reset and Ignored:"
11
+
12
+ if fsm.trigger(:confirm)
13
+ puts "Confirmed"
14
+ end
15
+
16
+ if fsm.trigger(:ignore)
17
+ puts "Ignored"
18
+ end
19
+
20
+ if fsm.trigger(:reset)
21
+ puts "Reset"
22
+ end
23
+
24
+ if fsm.trigger(:ignore)
25
+ puts "Ignored"
26
+ end
@@ -0,0 +1,16 @@
1
+ require 'microfsm'
2
+
3
+ # This example can be run with ruby -I lib/ ./examples/callbacks.rb
4
+
5
+ fsm = MicroFSM.new(:pending)
6
+ .when(:confirm, :pending => :confirmed) { puts "Confirmed" }
7
+ .when(:ignore, :pending => :ignored) { puts "Ignored" }
8
+ .when(:reset, :confirmed => :pending, :ignored => :pending) {
9
+ puts "Reset"
10
+ }
11
+
12
+ puts "Should print Confirmed, Reset and Ignored:"
13
+ fsm.trigger(:confirm)
14
+ fsm.trigger(:ignore)
15
+ fsm.trigger(:reset)
16
+ fsm.trigger(:ignore)
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MicroFSM
4
+ InvalidEvent = Class.new(NoMethodError)
5
+ InvalidState = Class.new(ArgumentError)
6
+ InvalidTransition = Class.new(ArgumentError)
7
+
8
+ attr_reader :state
9
+
10
+ def initialize(initial_state)
11
+ @state = initial_state
12
+ @transitions_for = {}
13
+ @callbacks_for = {}
14
+ end
15
+
16
+ def when(event, transitions, &block)
17
+ @transitions_for[event] ||= {}
18
+ @callbacks_for[event] ||= {}
19
+
20
+ transitions.each do |from, to|
21
+ nto = @transitions_for[event][from]
22
+ raise InvalidTransition if nto && nto != to
23
+
24
+ @transitions_for[event][from] = to
25
+ @callbacks_for[event][from] ||= []
26
+ @callbacks_for[event][from] << block if block_given?
27
+ end
28
+ self
29
+ end
30
+
31
+ def trigger(event)
32
+ trigger?(event) and transit(event)
33
+ end
34
+
35
+ def trigger!(event)
36
+ trigger(event) or
37
+ raise InvalidState.new("Event '#{event}' not valid from state '#{@state}'")
38
+ end
39
+
40
+ def trigger?(event)
41
+ raise InvalidEvent unless @transitions_for.has_key?(event)
42
+
43
+ @transitions_for[event].has_key?(state)
44
+ end
45
+
46
+ def events
47
+ @transitions_for.keys.sort
48
+ end
49
+
50
+ def triggerable_events
51
+ events.select { |event| trigger?(event) }.sort
52
+ end
53
+
54
+ def states
55
+ @transitions_for.values.map(&:to_a).flatten.uniq.sort
56
+ end
57
+
58
+ private
59
+ def transit(event)
60
+ callbacks = @callbacks_for[event][@state]
61
+ @state = @transitions_for[event][@state]
62
+ callbacks.each { |callback| callback.call(event) }
63
+ true
64
+ end
65
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MicroFSM
4
+ VERSION = '0.0.1' # 2021-01-24
5
+ end
@@ -0,0 +1,20 @@
1
+ $LOAD_PATH.push File.expand_path('lib', __dir__)
2
+ require 'version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "microfsm"
6
+ s.version = MicroFSM::VERSION
7
+ s.summary = %{Minimal Finite State Machine.}
8
+ # s.description = %Q{There are many finite state machine implementations for Ruby, and they all provide a nice DSL for declaring events, exceptions, callbacks, and all kinds of niceties in general.\n\nBut if all you want is a finite state machine, look no further: this has less than 50 lines of code and provides everything a finite state machine must have, and nothing more.}
9
+ s.authors = ['Dittmar Krall']
10
+ s.email = 'dittmar.krall@matique.de'
11
+ s.homepage = 'http://www.matique.de'
12
+ s.license = "MIT"
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+
16
+ s.add_development_dependency 'bundler'
17
+ s.add_development_dependency 'rake'
18
+
19
+ s.add_development_dependency 'minitest'
20
+ end
@@ -0,0 +1,35 @@
1
+ require 'test_helper'
2
+
3
+ describe MicroFSM do
4
+ let (:fsm) {
5
+ MicroFSM.new(:pending)
6
+ .when(:confirm, pending: :confirmed) { @state = "Confirmed" }
7
+ .when(:reset, confirmed: :pending) { @state = "Pending" }
8
+ }
9
+
10
+ def test_executes_callbacks_during_transition
11
+ fsm.trigger(:confirm)
12
+ assert_equal "Confirmed", @state
13
+
14
+ fsm.trigger(:reset)
15
+ assert_equal "Pending", @state
16
+ end
17
+
18
+ def test_two_callbacks_during_transition
19
+ fsm.when(:confirm, pending: :confirmed) { @state2 = "Confirmed2" }
20
+
21
+ fsm.trigger(:confirm)
22
+ assert_equal "Confirmed", @state
23
+ assert_equal "Confirmed2", @state2
24
+ end
25
+
26
+ def test_passing_the_event_name_to_the_callbacks
27
+ event_name = nil
28
+ fsm.when(:confirm, pending: :confirmed) do |event|
29
+ event_name = event
30
+ end
31
+
32
+ fsm.trigger(:confirm)
33
+ assert_equal :confirm, event_name
34
+ end
35
+ end
@@ -0,0 +1,22 @@
1
+ require 'test_helper'
2
+
3
+ describe MicroFSM do
4
+ let (:fsm) {
5
+ MicroFSM.new(:pending)
6
+ .when(:confirm, pending: :confirmed)
7
+ .when(:ignore, pending: :ignored)
8
+ .when(:reset, confirmed: :pending, ignored: :pending)
9
+ }
10
+
11
+ def test_returns_an_array_with_the_defined_events
12
+ assert_equal %i[confirm ignore reset], fsm.events
13
+ end
14
+
15
+ def test_list_the_available_events_for_the_current_state
16
+ assert_equal %i[confirm ignore], fsm.triggerable_events
17
+ end
18
+
19
+ def test_returns_an_array_with_the_defined_states
20
+ assert_equal %i[confirmed ignored pending], fsm.states
21
+ end
22
+ end
@@ -0,0 +1,65 @@
1
+ require 'test_helper'
2
+
3
+ describe MicroFSM do
4
+ let (:fsm) {
5
+ MicroFSM.new(:pending)
6
+ .when(:confirm, pending: :confirmed)
7
+ .when(:ignore, pending: :ignored)
8
+ .when(:reset, confirmed: :pending, ignored: :pending)
9
+ }
10
+
11
+ def test_class
12
+ assert_kind_of MicroFSM, fsm
13
+ end
14
+
15
+ def test_defines_initial_state
16
+ assert_equal :pending, fsm.state
17
+ end
18
+
19
+ def test_changes_the_state
20
+ assert fsm.trigger?(:confirm)
21
+ assert fsm.trigger(:confirm)
22
+ assert_equal :confirmed, fsm.state
23
+ end
24
+
25
+ def test_preserves_the_state_if_transition_is_not_possible
26
+ refute fsm.trigger?(:reset)
27
+ refute fsm.trigger(:reset)
28
+ assert_equal :pending, fsm.state
29
+ end
30
+
31
+ def test_multiple_transitions
32
+ fsm.trigger(:confirm)
33
+ assert_equal :confirmed, fsm.state
34
+
35
+ fsm.trigger(:reset)
36
+ assert_equal :pending, fsm.state
37
+
38
+ fsm.trigger(:ignore)
39
+ assert_equal :ignored, fsm.state
40
+
41
+ fsm.trigger(:reset)
42
+ assert_equal :pending, fsm.state
43
+ end
44
+
45
+ def test_raises_an_error_if_an_invalid_event_is_triggered
46
+ assert_raises(MicroFSM::InvalidEvent) do
47
+ fsm.trigger(:random_event)
48
+ end
49
+ end
50
+
51
+ def test_raises_error_if_trigger_from_incompatible_state
52
+ assert_raises(MicroFSM::InvalidState) do
53
+ fsm.trigger!(:reset)
54
+ end
55
+ end
56
+
57
+ def test_raises_an_error_if_a_transition_is_overwritten
58
+ fsm = MicroFSM.new(:init)
59
+
60
+ fsm.when(:trigger, init: :started)
61
+ assert_raises(MicroFSM::InvalidTransition) do
62
+ fsm.when(:trigger, init: :wrong)
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,11 @@
1
+ if ENV['COVERAGE']
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter 'test'
5
+ command_name 'Minitest'
6
+ end
7
+ end
8
+
9
+ require 'minitest/autorun'
10
+
11
+ require 'microfsm'
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: microfsm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dittmar Krall
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-01-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email: dittmar.krall@matique.de
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - ".rubocop.yml"
62
+ - ".ruby-gemset"
63
+ - ".ruby-version"
64
+ - ".watchr"
65
+ - Gemfile
66
+ - Gemfile.lock
67
+ - LICENSE
68
+ - README.md
69
+ - Rakefile
70
+ - examples/advanced.rb
71
+ - examples/basic.rb
72
+ - examples/callbacks.rb
73
+ - lib/microfsm.rb
74
+ - lib/version.rb
75
+ - microfsm.gemspec
76
+ - test/callbacks_test.rb
77
+ - test/introspection_test.rb
78
+ - test/microfsm_test.rb
79
+ - test/test_helper.rb
80
+ homepage: http://www.matique.de
81
+ licenses:
82
+ - MIT
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubygems_version: 3.1.4
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: Minimal Finite State Machine.
103
+ test_files: []