y_support 2.0.11 → 2.0.13

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bc98d20ebfbbb5861b8ec817347e5d73a71e4518
4
- data.tar.gz: 1226960b1bc6b9e15a0c1626816266378fa489de
3
+ metadata.gz: d466ad84213f9677a44efdb9d426ae1a24c11688
4
+ data.tar.gz: 398a4cbaf4e656dcabd8d87055c5069bcef90275
5
5
  SHA512:
6
- metadata.gz: 070a617610e329aa6a5ca5ac868ab3f875864485626e4db658da11bade01e37fb64f56a9323d41dc2a98acbac23e440bf3abb15a2d25fd4a0803d9c639713cda
7
- data.tar.gz: 68f0b3f5b32caa61bc0fe44391d1946ca25dc6e394dbdc23fdcfe3e63d5b7d8489f9906a691d3b71107b4993a35192f65f452ee33a1a7628d34d4414718b65c7
6
+ metadata.gz: ace20c52c5676019cdf9b1633911a134903db65a3bca738e478172ea3d826e4485ab957b4f541fd21e2e0ab924b3ae9336ce5c6922be5ac7252edad5ed893bdf
7
+ data.tar.gz: cf26fc0b943d41e39af89f4dbb8025e258733fea47497a6f5be8b030125ccd0efbeb24212dd852833949111fb312f0acb1ea11e7f1e8f19570d9c7a361e6ca0b
data/lib/y_support/all.rb CHANGED
@@ -8,6 +8,7 @@ require 'y_support/respond_to'
8
8
  require 'y_support/null_object'
9
9
  require 'y_support/inert_recorder'
10
10
  require 'y_support/local_object'
11
+ require 'y_support/try'
11
12
  require 'y_support/abstract_algebra'
12
13
  require 'y_support/kde'
13
14
  require 'y_support/x'
@@ -0,0 +1,132 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'y_support'
4
+ require 'y_support/core_ext/array/misc'
5
+
6
+ # Provides +Try+ class, and +Object#try+ method that constructs and calls a
7
+ # +Consciously::Try+ instance. This +#try+ method has nothing to do with the
8
+ # error-swallowing +#try+ method frequently seen elsewhere. On the contrary,
9
+ # our +#try+ method _facilitates_ raising and ultimately, correcting errors
10
+ # by providing well-formed error messages.
11
+ #
12
+ # Constructing error messages is labor-intensive. +Consciously::Try+ allows one
13
+ # to construct verbose error messages with +#note+ statements inside the block,
14
+ # that act as comments at the same time.
15
+ #
16
+ # "FooBar".try "to do something" do
17
+ # note has: "#{size} letters", is: "a #{self.class} instance"
18
+ # unless include? "Quux"
19
+ # note "Quux", is: "not a part of it"
20
+ # try "to append Quux to it" do
21
+ # self << "Quux"
22
+ # fail "EPIC FAIL"
23
+ # end
24
+ # end
25
+ # end
26
+ #
27
+ # Should produce an automatic error message like this: "When trying to do
28
+ # something, FooBar having 6 letters, being a String instance, Quux being
29
+ # not a part of it, RuntimeError occurred: When trying to append Quux to it,
30
+ # RuntimeError occurred: EPIC FAIL"
31
+ #
32
+ module Consciously
33
+ class Try < BasicObject
34
+ DECORATE = -> str, prefix: '', postfix: '' {
35
+ str.to_s.tap { |ς| return ς.empty? ? '' : prefix + ς + postfix }
36
+ }
37
+ TRANSITIVE = ::Hash.new do |ꜧ, key| "#{key}ing %s" end
38
+ .update( is: "being %s",
39
+ has: "having %s" )
40
+ STATE = ::Hash.new do |ꜧ, key| "#{key} %s" end
41
+ .update( is: "%s",
42
+ has: "has %s" )
43
+
44
+ attr_reader :__obj__, :__txt__, :__bl__, :__facts__
45
+
46
+ # This
47
+ def initialize( object: nil, text: nil, &block )
48
+ @__obj__, @__txt__, @__bl__ = object, text, block
49
+ @__facts__ = ::Hash.new do |hsh, key| hsh[key] = [ {} ] end
50
+ end
51
+
52
+ # The syntax of this method, available inside the #try block, is:
53
+ #
54
+ # note "Concatenation of Foo and Bar", is: "FooBar", has: "6 letters"
55
+ #
56
+ def note *subjects, **statements, &block
57
+ return Array( subjects ).each { |s| __facts__[s].push_ordered s } if
58
+ statements.empty?
59
+ subjects << __obj__ if subjects.empty?
60
+ Array( subjects ).each { |subj|
61
+ statements.each { |verb, obj| __facts__[subj].push_named verb => obj }
62
+ }
63
+ return statements.first[1]
64
+ end
65
+
66
+ # Invokes the Try object's block.
67
+ #
68
+ def __invoke__ *args
69
+ begin
70
+ instance_exec *args, &__bl__
71
+ rescue ::StandardError => err
72
+ txt1 = "When trying #{__txt__}"
73
+ thing, statements = __describe__
74
+ txt2 = DECORATE.( thing, prefix: ' ' )
75
+ txt3 = DECORATE.( statements.map { |verb, object|
76
+ STATE[verb] % object
77
+ }.join( ', ' ),
78
+ prefix: ' (', postfix: ')' )
79
+ txt4 = DECORATE.( __circumstances__, prefix: ', ' )
80
+ txt5 = DECORATE.( "#{err.class} occurred: #{err}", prefix: ', ' )
81
+ raise err, txt1 + txt2 + txt3 + txt4 + txt5
82
+ end
83
+ end
84
+
85
+ def try *args, &block
86
+ __obj__.try *args, &block
87
+ end
88
+
89
+ def method_missing sym, *args
90
+ __obj__.send sym, *args
91
+ end
92
+
93
+ def __describe__ obj=__obj__
94
+ facts = __facts__[obj].dup
95
+ statements = if facts.last.is_a? ::Hash then facts.pop else {} end
96
+ fs = facts.join ', '
97
+ if statements.empty? then
98
+ return fs, statements
99
+ else
100
+ return facts.empty? ? obj.to_s : fs, statements
101
+ end
102
+ end
103
+
104
+ def __circumstances__
105
+ __facts__.reject { |subj, _| subj == __obj__ }.map { |subj, _|
106
+ thing, statements = __describe__( subj )
107
+ thing + DECORATE.( statements.map { |v, o|
108
+ TRANSITIVE[v] % o
109
+ }.join( ', ' ),
110
+ prefix: ' ' )
111
+ }.join( ', ' )
112
+ end
113
+ end
114
+ end
115
+
116
+
117
+ class Object
118
+ # Try method takes two textual arguments and one block. The first (optional)
119
+ # argument is a natural language description of the method's receiver (with
120
+ # #to_s of the receiver used by default). The second argument is a natural
121
+ # language description of the supplied block's _contract_ -- in other words,
122
+ # what the supplied block tries to do. Finally, the block contains the code
123
+ # to perform the described risky action. Inside the block, +#note+ method is
124
+ # available, which builds up the context information for a good error message,
125
+ # should the risky action raise one.
126
+ #
127
+ def try receiver_NL_description=self, attempt_NL_description, &block
128
+ Consciously::Try.new( object: receiver_NL_description,
129
+ text: attempt_NL_description,
130
+ &block ).__invoke__
131
+ end
132
+ end
@@ -1,3 +1,3 @@
1
1
  module YSupport
2
- VERSION = "2.0.11"
2
+ VERSION = "2.0.13"
3
3
  end
data/test/try_test.rb ADDED
@@ -0,0 +1,103 @@
1
+ #! /usr/bin/ruby
2
+
3
+ require 'minitest/spec'
4
+ require 'minitest/autorun'
5
+ # require 'y_support/try' # tested component itself
6
+ require './../lib/y_support/try'
7
+
8
+ describe Consciously do
9
+ before do
10
+ @try = Consciously::Try.new object: "Dummy", text: "to fire" do
11
+ note is: "dummy"
12
+ note has: "no care in the world"
13
+ n = note "its number", is: 42
14
+ raise TypeError, 'foo'
15
+ end
16
+ end
17
+
18
+ it "should have basic functionality" do
19
+ assert_equal "to fire", @try.__txt__
20
+ assert_equal "Dummy", @try.__obj__
21
+ assert_equal 0, @try.__facts__.size # haven't tried anything yet
22
+ @try.__facts__["something"]
23
+ assert_equal 1, @try.__facts__.size
24
+ @try.note is: 'dummy'
25
+ @try.note has: 'no care in the world'
26
+ assert_equal 2, @try.__facts__.size
27
+ assert_equal ["something", "Dummy"], @try.__facts__.keys
28
+ assert_equal( [ { is: "dummy", has: "no care in the world" } ],
29
+ @try.__facts__["Dummy"] )
30
+ assert_equal " hello!", Consciously::Try::DECORATE.( :hello, prefix: ' ', postfix: '!' )
31
+ assert_equal( ['Dummy', {is: 'dummy', has: 'no care in the world'}],
32
+ @try.__describe__( "Dummy" ) )
33
+ end
34
+
35
+ describe 'case 1' do
36
+ it "should work" do
37
+ begin
38
+ @try.__invoke__
39
+ rescue TypeError => err
40
+ expected_msg = "When trying to fire Dummy (dummy, has no care in " +
41
+ "the world), its number being 42, TypeError occurred: foo"
42
+ assert_equal expected_msg, err.message
43
+ else
44
+ flunk "Expected TypeError error not raised!"
45
+ end
46
+ end
47
+ end
48
+
49
+ describe 'case 2' do
50
+ it "should work" do
51
+ begin
52
+ try "to call constant Nonexistant" do Nonexistant end
53
+ rescue NameError => err
54
+ expected_msg = 'When trying to call constant Nonexistant, ' +
55
+ 'NameError occurred: uninitialized constant Nonexistant'
56
+ assert_equal( expected_msg, err.message )
57
+ else
58
+ flunk "Expected NameError error not raised!"
59
+ end
60
+ end
61
+ end
62
+
63
+ describe 'case 3' do
64
+ it "should work" do
65
+ o = Object.new
66
+ class << o
67
+ def to_s; "THIS OBJECT" end
68
+ def hello!; "hello hello" end
69
+ end
70
+ # Object's methods must be callable
71
+ o.try "to say hello" do hello! end.must_equal "hello hello"
72
+ begin
73
+ o.try "to call a weird method" do goodbye! end
74
+ rescue NoMethodError => err
75
+ err.message.must_include "When trying to call a weird method, " +
76
+ "NoMethodError occurred: undefined method"
77
+ err.message.must_include "goodbye!"
78
+ end
79
+ end
80
+ end
81
+
82
+ describe 'case 4' do
83
+ it "should work" do
84
+ begin
85
+ "FooBar".try "to do something" do
86
+ note has: "#{size} letters", is: "a #{self.class} instance"
87
+ unless include? "Quux"
88
+ note "Quux", is: "not a part of it"
89
+ try "to append Quux to it" do
90
+ self << "Quux"
91
+ fail "EPIC FAIL"
92
+ end
93
+ end
94
+ end
95
+ rescue => err
96
+ err.message.must_equal 'When trying to do something, FooBar having ' +
97
+ '6 letters, being a String instance, Quux being not a part of it, ' +
98
+ 'RuntimeError occurred: When trying to append Quux to it, ' +
99
+ 'RuntimeError occurred: EPIC FAIL'
100
+ end
101
+ end
102
+ end
103
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: y_support
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.11
4
+ version: 2.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - boris
@@ -53,7 +53,6 @@ files:
53
53
  - lib/y_support.rb
54
54
  - lib/y_support/abstract_algebra.rb
55
55
  - lib/y_support/all.rb
56
- - lib/y_support/conscience.rb
57
56
  - lib/y_support/core_ext.rb
58
57
  - lib/y_support/core_ext/array.rb
59
58
  - lib/y_support/core_ext/array/misc.rb
@@ -81,6 +80,7 @@ files:
81
80
  - lib/y_support/stdlib_ext.rb
82
81
  - lib/y_support/stdlib_ext/matrix.rb
83
82
  - lib/y_support/stdlib_ext/matrix/misc.rb
83
+ - lib/y_support/try.rb
84
84
  - lib/y_support/typing.rb
85
85
  - lib/y_support/typing/array.rb
86
86
  - lib/y_support/typing/array/typing.rb
@@ -96,7 +96,6 @@ files:
96
96
  - lib/y_support/version.rb
97
97
  - lib/y_support/x.rb
98
98
  - test/abstract_algebra_test.rb
99
- - test/conscience_test.rb
100
99
  - test/inert_recorder_test.rb
101
100
  - test/kde_test.rb
102
101
  - test/local_object_test.rb
@@ -105,6 +104,7 @@ files:
105
104
  - test/name_magic_test.rb
106
105
  - test/null_object_test.rb
107
106
  - test/respond_to_test.rb
107
+ - test/try_test.rb
108
108
  - test/typing_test.rb
109
109
  - test/unicode_test.rb
110
110
  - test/x_test.rb
@@ -135,7 +135,6 @@ summary: LocalObject, RespondTo, InertRecorder, NullObject, NameMagic, core exte
135
135
  typing etc.
136
136
  test_files:
137
137
  - test/abstract_algebra_test.rb
138
- - test/conscience_test.rb
139
138
  - test/inert_recorder_test.rb
140
139
  - test/kde_test.rb
141
140
  - test/local_object_test.rb
@@ -144,6 +143,7 @@ test_files:
144
143
  - test/name_magic_test.rb
145
144
  - test/null_object_test.rb
146
145
  - test/respond_to_test.rb
146
+ - test/try_test.rb
147
147
  - test/typing_test.rb
148
148
  - test/unicode_test.rb
149
149
  - test/x_test.rb
@@ -1,132 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require 'y_support'
3
- require 'active_support/core_ext/array/extract_options'
4
-
5
- # FIXME: Now, here, in order for the token game to work properly with
6
- # guarding system, several things have to be done. Firstly,
7
- # Place#set_marking( marking, blame ) will have to be implemented,
8
- # and in Place#add, blame argument will have to be added
9
- # Now with that blame, the transition will have to explain what it is
10
- # trying to do. So actually it should be a block
11
- #
12
- # It's gonna be a mixin, Conscience, or something like that, and it will
13
- # imbue the receiving class with the ability to try something.
14
- #
15
- # Transition.try "to fire!" do
16
- # if assignment_action? then
17
- # note has: "assignment action"
18
- # note "Δt", is: Δt
19
- # note "domain marking" is: domain_marking
20
- # act = note "Action" do Array action( Δt ) end
21
- # codomain.each_with_index do |place, i|
22
- # try "set the marking of place #{place} to the #{i}-th element of the action vector (#{act[i]})" do
23
- # place.marking = act[i]
24
- # end
25
- # end
26
- # else
27
- # etc. etc. etc.
28
- # end
29
- #
30
- # Should produce error messages like this:
31
- # When trying to fire! the transition #{self}, having assignment action, with Δt being #{Δt}, action has
32
- # been computed to #{Array action(Δt)}, when trying to set the marking of plac #{place} to the #{i}-th
33
- # element of the action vector (#{act[i]}), GuardError was encountered, with the message: ..."
34
- #
35
- # Yes, this is a managed code miniframework that I need here.
36
- #
37
- module Conscience
38
- class Try
39
- PUSH_ORDERED = -> ary, e {
40
- named = ary.extract_options!
41
- ary << e << named
42
- }
43
- PUSH_NAMED = -> ary, k, v {
44
- named = ary.extract_options!
45
- ary << named.update( k => v )
46
- }
47
- DECORATE = -> str, prefix: '', postfix: '' {
48
- str.to_s.tap { |ς| return ς.empty? ? '' : prefix + ς + postfix }
49
- }
50
- TRANSITIVE = Hash.new do |ꜧ, key| "#{key}ing %s" end
51
- .update( is: "being %s",
52
- has: "having %s" )
53
- STATE = Hash.new do |ꜧ, key| "#{key} %s" end
54
- .update( is: "%s",
55
- has: "has %s" )
56
-
57
- attr_reader :_object_, :_text_, :_block_, :_facts_
58
-
59
- def initialize( object: nil, text: nil, &block )
60
- @_object_, @_text_, @_block_ = object, text, block
61
- @_facts_ = Hash.new do |ꜧ, key| ꜧ[key] = [ {} ] end
62
- end
63
-
64
- def note *subjects, **statements, &block
65
- return *Array( subjects ).each do |s|
66
- PUSH_ORDERED.( _facts_[s], s )
67
- end if statements.empty?
68
- subjects << _object_ if subjects.empty?
69
- Array( subjects ).each do |subj|
70
- statements.each do |verb, object|
71
- PUSH_NAMED.( _facts_[subj], verb, object )
72
- end
73
- end
74
- return statements.first[1]
75
- end
76
-
77
- def call *args
78
- begin
79
- instance_exec *args, &_block_
80
- rescue StandardError => err
81
- txt1 = "When trying #{_text_}"
82
- thing, statements = _describe_
83
- txt2 = DECORATE.( thing, prefix: ' ' )
84
- txt3 = DECORATE.( statements.map { |verb, object|
85
- STATE[verb] % object
86
- }.join( ', ' ),
87
- prefix: ' (', postfix: ')' )
88
- txt4 = DECORATE.( _circumstances_, prefix: ', ' )
89
- txt5 = DECORATE.( "#{err.class} occurred: #{err}", prefix: ', ' )
90
- raise err, txt1 + txt2 + txt3 + txt4 + txt5
91
- end
92
- end
93
-
94
- def method_missing sym, *args
95
- _object_.send sym, *args
96
- end
97
-
98
- private
99
-
100
- def _describe_ obj=_object_
101
- facts = _facts_[obj].dup
102
- statements = facts.extract_options!
103
- fs = facts.join ', '
104
- if statements.empty? then
105
- return fs, statements
106
- else
107
- return facts.empty? ? obj.to_s : fs, statements
108
- end
109
- end
110
-
111
- def _circumstances_
112
- _facts_.reject { |subj, _| subj == _object_ }.map { |subj, _|
113
- thing, statements = _describe_( subj )
114
- thing + DECORATE.( statements.map { |v, o|
115
- TRANSITIVE[v] % o
116
- }.join( ', ' ),
117
- prefix: ' ' )
118
- }.join( ', ' )
119
- end
120
- end
121
-
122
- # Try method taxes two textual arguments and one block. The first (optional)
123
- # textual argument describes what is the receiver of #try. The second argument
124
- # describes in plain speech what activity is #try attempting. The block that
125
- # follows then contains the code, which performs that activity. In the block,
126
- # #note method is available, that builds up the context for the error message,
127
- # if any.
128
- #
129
- def try object=self, to_do_something, &block
130
- Try.new( object: object, text: to_do_something, &block ).call
131
- end
132
- end
@@ -1,75 +0,0 @@
1
- #! /usr/bin/ruby
2
-
3
- require 'minitest/spec'
4
- require 'minitest/autorun'
5
- # require 'y_support/conscience' # tested component itself
6
- require './../lib/y_support/conscience'
7
-
8
- include Conscience
9
-
10
- describe Try do
11
- before do
12
- @try = Try.new object: "Dummy", text: "to fire" do
13
- note is: "dummy"
14
- note has: "no care in the world"
15
- n = note "the number", is: 42
16
- raise TypeError, 'foo'
17
- end
18
- end
19
-
20
- it "should have basic functionality" do
21
- assert_equal "to fire", @try._text_
22
- assert_equal "Dummy", @try._object_
23
- assert_equal 0, @try._facts_.size # haven't tried anything yet
24
- @try._facts_["something"]
25
- assert_equal 1, @try._facts_.size
26
- @try.note is: 'dummy'
27
- @try.note has: 'no care in the world'
28
- assert_equal 2, @try._facts_.size
29
- assert_equal ["something", "Dummy"], @try._facts_.keys
30
- assert_equal( [ { is: "dummy", has: "no care in the world" } ],
31
- @try._facts_["Dummy"] )
32
- assert_equal " hello!", Try::DECORATE.( :hello, prefix: ' ', postfix: '!' )
33
- assert_equal( ['Dummy', {is: 'dummy', has: 'no care in the world'}],
34
- @try.send( :_describe_, "Dummy" ) )
35
- end
36
-
37
- describe 'case 1' do
38
- it "should work" do
39
- begin
40
- @try.call
41
- rescue TypeError => err
42
- expected_msg = "When trying to fire Dummy (dummy, has no care in " +
43
- "the world), the number being 42, TypeError occurred: foo"
44
- assert_equal expected_msg, err.message
45
- else
46
- flunk "Expected TypeError error not raised!"
47
- end
48
- end
49
- end
50
-
51
- describe 'case 2' do
52
- it "should work" do
53
- begin
54
- try "to call constant Nonexistant" do Nonexistant end
55
- rescue NameError => err
56
- expected_msg = 'When trying to call constant Nonexistant, ' +
57
- 'NameError occurred: uninitialized constant Nonexistant'
58
- assert_equal( expected_msg, err.message )
59
- else
60
- flunk "Expected NameError error not raised!"
61
- end
62
- end
63
- end
64
-
65
- describe 'case 3' do
66
- it "should work" do
67
- o = Object.new
68
- class << o
69
- def to_s; "THIS OBJECT" end
70
- def hello!; "hello hello" end
71
- end
72
- o.try "to call a missing method" do hello! end
73
- end
74
- end
75
- end