dbg_tags 1.0.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 (4) hide show
  1. checksums.yaml +7 -0
  2. data/lib/dbg_tags.rb +145 -0
  3. data/spec/01_tag_spec.rb +181 -0
  4. metadata +105 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f67668ea968705e3998d9481a23a32d12fd5db9f42a53d97f6f7f1383f424372
4
+ data.tar.gz: d2ea2f479005e3d652629749b1c5d7cb2304140ca56de952c8c6b35fe3078e50
5
+ SHA512:
6
+ metadata.gz: ad6860e2153812cede77a7bc1c56c16720e553e3fb1a90fc3922349f578738dd3d242e5622636327a80199038741298f407905f99f3684b8cf42e9a3c65d268e
7
+ data.tar.gz: 3b68a1bfffc89b93d2344f72662d0046b0d8d410047abd856f15df3f75f46d1e783cf03748478a32231c60e2d0e026b488ff2ed4655d487a27edb48f1b5ad4f7
data/lib/dbg_tags.rb ADDED
@@ -0,0 +1,145 @@
1
+
2
+ # Usage:
3
+ # require 'dbg_tags'
4
+ # Tag.err 'text', short for Tag.err(:generic) 'text'
5
+ # # :err should be used for fail states and paranoia stuff
6
+ # Tag.log 'text' # prints very important messages only
7
+ # Tag.trc 'text' # default level, method entries, for example
8
+ # Tag.val 'text' # prints more details
9
+ # Tag.dtl 'text' # prints megabytes of details
10
+ # Tag.enable :log # enables log,trc,val,dtl tags for :generic
11
+ # Tag.enable :dtl # only enables :dtl calls
12
+ # Tag.enable :err # enable ALL :generic tags
13
+ # Tag.err :feature, 'FAILURE'
14
+ # Tag.log :feature, 'log me'
15
+ # Tag.trc :feature, 'called method'
16
+ # Tag.val(:feature) { "text#{expr}" }
17
+ # Tag.dtl(:feature) { "text#{very complicated expr}" }
18
+ # Tag.err(:test) { raise 'aaaarg' if paranoia_failure }
19
+ # Tag.err(:test) { raise 'CANTHAPPEN' if paranoia_failure }
20
+ # Tag.enable :feature1, :feature2..., featureN: :log, featureO: :val, ...
21
+ # Tag.enable feature1: :trc, feature2: :val
22
+ # Tag.enable feature: Tag::TRC
23
+ # Tag.enable :val # for :generic only
24
+ # Tag.enable # sets :generic to :trc
25
+ # Tag.enable(...) do ... end
26
+ # Tag.enable feature: nil
27
+ # Tag.enable feature: :nil
28
+ # Tag.enable all: :err # :all is a default for ALL systems, including :generic
29
+ # Tag.enable test: :err # switch on paranoia checking
30
+ module Tag
31
+
32
+ TAG_DEFAULT_LEVEL = 3
33
+ TAG_FEATURE_ALL = :all
34
+ TAG_FEATURE_GENERIC = :generic
35
+ NONE = 0
36
+ ERR = 1
37
+ LOG = 2
38
+ TRC = 3
39
+ VAL = 4
40
+ DTL = 5
41
+ # nil and :nil will both map to NONE
42
+ TAG_MAPPING = { none: NONE, err: ERR, log: LOG, trc: TRC, val: VAL, dtl: DTL,
43
+ nil: NONE,
44
+ nil => NONE
45
+ } # TAG_MAPPING
46
+
47
+ # @@enabled[:feature] => 0..5
48
+ @@enabled = {}
49
+ @@stream = STDERR
50
+
51
+ module InstanceMethods
52
+ @@inside = false
53
+
54
+ TAG_MAPPING.each do |meth, lev|
55
+ next if lev == NONE
56
+ define_method meth do |feature = TAG_FEATURE_GENERIC, msg = '', &msg_block|
57
+ msg, feature = feature, TAG_FEATURE_GENERIC if String === feature
58
+ #STDERR.puts "DEBUGTAG #{meth}. feature=#{feature}, level=#{Tag.level(feature)}, lev=#{lev}"
59
+ return if @@inside || (Tag.level(feature) || 0) < lev
60
+ # either msg OR msg_block must be set
61
+ if msg_block
62
+ prev_inside = @@inside
63
+ begin
64
+ @@inside = true
65
+ msg = msg_block.call
66
+ ensure
67
+ @@inside = prev_inside
68
+ end
69
+ end
70
+ if msg
71
+ c = caller[0]
72
+ #STDERR.puts "DEBUGTAG c[#{idx}] = #{c}, caller[1]=#{caller[1]}, caller[2]=#{caller[2]}"
73
+ label = c[/\w+\.rb:\d+:in `[^']+'/]&.sub(/in `([^']+)'/, '\1:') ||
74
+ c[/\w+\.rb:\d+:/] ||
75
+ c[/[^:\/]+:\d+:/] ||
76
+ c
77
+ Tag.stream.print "#{label} #{msg}\n"
78
+ end
79
+ end # Tag.err, Tag.log, Tag.trc, Tag.val, Tag.dtl
80
+ end # each
81
+
82
+ # inside? -> true if we are currently executing a block in err/log/trc/val or dtl.
83
+ def inside?; @@inside; end
84
+
85
+ end # module Tag::InstanceMethods
86
+
87
+ public # class methods of Tag
88
+
89
+ extend InstanceMethods
90
+ include InstanceMethods
91
+
92
+ # enable :feature, ...[, feature: level, ...] [block]
93
+ # :generic is NO LONGER IMPLICETELY ENABLED as of version
94
+ # Use :all to set a default for all features not mentioned otherwise
95
+ # Integers in range 1..5 can be used as level or the constants ERR,LOG,TRC,VAL,DTL
96
+ # or the symbols :err, :log, :trc, :val and :dtl
97
+ # If no level is specified for a feature the default is :trc (== TRC == 3)
98
+ # use nil or :none to disable all tags, even the ERR level ones.
99
+ #
100
+ # enable performs a merge with an existing enable.
101
+ def self.enable *arg
102
+ org_enabled = @@enabled.dup
103
+ arg.each do |s|
104
+ case s
105
+ when Hash
106
+ s.each do |t, level|
107
+ @@enabled[t] = Symbol === level ? TAG_MAPPING[level] : level
108
+ end
109
+ when Integer
110
+ @@enabled[TAG_FEATURE_GENERIC] = s
111
+ else
112
+ if TAG_MAPPING[s]
113
+ @@enabled[TAG_FEATURE_GENERIC] = TAG_MAPPING[s]
114
+ else
115
+ @@enabled[s] = TAG_DEFAULT_LEVEL
116
+ end
117
+ end # case
118
+ end # each
119
+ if arg.empty?
120
+ @@enabled[TAG_FEATURE_GENERIC] = TAG_DEFAULT_LEVEL
121
+ end
122
+ if block_given?
123
+ # STDERR.puts "TAG: block_given!"
124
+ begin
125
+ # STDERR.puts "TAG: yield!"
126
+ yield
127
+ ensure
128
+ @@enabled = org_enabled
129
+ end # ensure
130
+ end # block_given?
131
+ end # Tag.enable
132
+
133
+ # enabled -> Hash
134
+ def self.enabled; @@enabled; end
135
+ def self.stream; @@stream; end
136
+
137
+ # for testing purposes:
138
+ def self.stream= val; @@stream = val; end
139
+
140
+ # level(:feature) -> 0..5 or nil. Uses :all as a fallback-feature
141
+ def self.level feature; @@enabled[feature] || @@enabled[TAG_FEATURE_ALL]; end
142
+
143
+ # enabled?(:feature) -> bool. Could be :err up to :dtl. Ignores setting of :all!
144
+ def self.enabled? feature; @@enabled[feature] && @@enabled[feature] > NONE; end
145
+ end # module Tag
@@ -0,0 +1,181 @@
1
+
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+
5
+ require_relative '../lib/dbg_tags'
6
+
7
+ class Pathological
8
+ def to_s
9
+ Tag.trc { "HERE in #{self}!" }
10
+ super
11
+ end # to_s
12
+ end
13
+
14
+ describe 'tag' do
15
+ before :each do
16
+ @stream = double 'stream'
17
+ Tag.stream = @stream
18
+ end # before :each
19
+
20
+ it 'prints stuff while enabled (tag_001)' do
21
+ expect(@stream).to receive(:print).once
22
+ Tag.enable :dtl do
23
+ Tag.trc 'this is traced'
24
+ end # enable
25
+ Tag.trc 'this is outside scope'
26
+ end # it
27
+
28
+ it 'prints stuff only if the level is high enough (tag_002)' do
29
+ expect(@stream).to_not receive :print
30
+ Tag.enable :val do
31
+ Tag.dtl 'this is not traced'
32
+ end # enable
33
+ end # it
34
+
35
+ it 'prints stuff only if the level is high enough (tag_003)' do
36
+ expect(@stream).to receive(:print).once
37
+ Tag.enable :trc do
38
+ Tag.err 'this is traced'
39
+ Tag.val 'this is not traced'
40
+ Tag.dtl 'this is not traced'
41
+ end # enable
42
+ end # it
43
+
44
+ it 'prints stuff only if the level is high enough (tag_004)' do
45
+ expect(@stream).to receive(:print).once
46
+ Tag.enable :log do
47
+ Tag.log 'this is traced'
48
+ Tag.trc 'this is not traced'
49
+ Tag.val 'this is not traced'
50
+ Tag.dtl 'this is not traced'
51
+ end # enable
52
+ end # it
53
+
54
+ it 'prints stuff only if the level is high enough (tag_005)' do
55
+ expect(@stream).to receive(:print).once
56
+ Tag.enable :err do
57
+ Tag.err 'this is traced'
58
+ Tag.log 'this is not traced'
59
+ Tag.trc 'this is not traced'
60
+ Tag.val 'this is not traced'
61
+ Tag.dtl 'this is not traced'
62
+ end # enable
63
+ end # it
64
+
65
+ it 'allows constants for setting the level too (tag_006)' do
66
+ expect(@stream).to receive(:print).twice
67
+ Tag.enable Tag::LOG do
68
+ Tag.err 'this is traced'
69
+ Tag.log 'this is traced'
70
+ Tag.trc 'this is not traced'
71
+ Tag.val 'this is not traced'
72
+ Tag.dtl 'this is not traced'
73
+ end # enable
74
+ end # it
75
+
76
+ it 'prints stuff only if the feature category is set correctly (tag_010)' do
77
+ expect(@stream).to receive(:print).once
78
+ Tag.enable generic: :trc do
79
+ Tag.trc 'this is traced'
80
+ Tag.trc :feature, 'this is not traced'
81
+ end
82
+ end # it
83
+
84
+ it 'uses :generic as default feature category (tag_015)' do
85
+ expect(@stream).to receive(:print).once.with(/this is traced/)
86
+ Tag.enable :trc do
87
+ Tag.trc 'this is traced'
88
+ Tag.trc :feature, 'this is not traced'
89
+ end
90
+ end # it
91
+
92
+ it 'can enable several cats with their own levels (tag_020)' do
93
+ expect(@stream).to receive(:print).exactly(2).times.with(/this is traced/)
94
+ Tag.enable core: :trc, printing: :val, calc: :err do
95
+ Tag.trc :core, 'this is traced'
96
+ Tag.trc :printing, 'this is traced'
97
+ Tag.trc :emit, 'this is not traced'
98
+ Tag.trc :calc, 'this is not traced'
99
+ end
100
+ end # it
101
+
102
+ it 'prints the line of the source where the tag was placed (tag_030)' do
103
+ expect(@stream).to receive(:print).once.with(/01_tag_spec.rb:\d+:block/)
104
+ Tag.enable core: :trc, printing: :val, calc: :err do
105
+ Tag.trc :core
106
+ end
107
+ Tag.trc :core, 'outside scope'
108
+ end # it
109
+
110
+ it 'allows a block for lazy evaluation (tag_040)' do
111
+ x = 0
112
+ expect(@stream).to receive(:print).once.with(/this is traced/)
113
+ Tag.enable core: :trc do
114
+ Tag.trc(:core) { x += 2; 'this is traced' }
115
+ Tag.val(:core) { x += 1 }
116
+ end
117
+ expect(x).to be 2
118
+ end # it
119
+
120
+ it 'allows non-strings in blocks (tag_041)' do
121
+ expect(@stream).to receive(:print).once.with(/\b2828\b/)
122
+ Tag.enable core: :trc do
123
+ Tag.trc(:core) { 2828 }
124
+ end
125
+ end # it
126
+
127
+ it 'allows for a level :nil (tag_050)' do
128
+ expect(@stream).to_not receive :print
129
+ Tag.enable :nil do
130
+ Tag.trc 'never'
131
+ Tag.err 'never'
132
+ end
133
+ end # it
134
+
135
+ it 'uses :trc as default level (tag_051)' do
136
+ expect(@stream).to receive(:print).once.with(/this is printed/)
137
+ Tag.enable do
138
+ Tag.trc 'this is printed'
139
+ Tag.val 'this is not printed'
140
+ end
141
+ end # it
142
+
143
+ it 'uses :trc as default level (tag_052)' do
144
+ expect(@stream).to receive(:print).twice.with(/this is printed/)
145
+ Tag.enable :core, :printing, emit: :err do
146
+ Tag.trc 'this is not printed'
147
+ Tag.trc :core, 'this is printed'
148
+ Tag.trc :printing, 'this is printed'
149
+ Tag.trc :emit, 'this is not printed'
150
+ end
151
+ end # it
152
+
153
+ it 'can set a default level using RESERVED category :all (tag_060)' do
154
+ expect(@stream).to receive(:print).exactly(3).times.with(/this is printed/)
155
+ Tag.enable :core, :printing, all: :err do
156
+ Tag.trc(:core) { 'this is printed' }
157
+ Tag.trc(:emit) { 'this is not printed' }
158
+ Tag.err(:emit) { 'this is printed' }
159
+ Tag.err(:anything) { 'this is printed' }
160
+ end # enable
161
+ end # it
162
+
163
+ it 'can handle pathological cases (tag_100)' do
164
+ expect(@stream).to receive(:print).once.with(/p =/)
165
+ Tag.enable do
166
+ p = Pathological.new
167
+ Tag.trc { "p = #{p}" }
168
+ end
169
+ end
170
+
171
+ it 'can handle pathological cases (tag_101)' do
172
+ expect(@stream).to receive(:print).once.with(/HERE/)
173
+ Tag.enable do
174
+ Pathological.new.to_s
175
+ end
176
+ end
177
+
178
+ # however, it only works with LAZY calls.
179
+ # def to_s; Tag.trc "HERE in #{self}"; super; end
180
+ # will OBVIOUSLY cause a stack overflow.
181
+ end # describe
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dbg_tags
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Eugene Brazwick
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-03-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.4'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.4'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: simplecov
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.18'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.18'
55
+ description: " tags in your code can be switched on using features and levels.\n
56
+ \ Examples:\n Tag.trc 'a message' # a :generic tag\n # All tags
57
+ print sourcefile, current method and linenumber automatically\n Tag.trc # prints
58
+ file, method and linenumber\n Tag.trc :feature, 'a message' # only called if
59
+ :feature enabled.\n Tag.err 'msg' # Triggered when :generic feature is set
60
+ to at \n # least :err level.\n # The levels
61
+ are :err, :log, :trc, :val and :dtl, \n # in that order\n Tag.dtl
62
+ :complex do \"val = #{expensive.method.call}\" end\n Tag.dtl(:complex) { \"val
63
+ = #{expensive.method.call}\" }\n\t # use lazy evaluation with a block.\n #
64
+ The block expression is printed using to_s.\n Tag.dtl(:complex) {} # same as
65
+ Tag.dtl :complex \n# At the start of your application enable the desired dump-level.\n
66
+ \ Tag.enable\t# Same as Tag.enable generic: :trc\n #
67
+ That is enables levels <=:trc\n Tag.enable :val # enable :generic tags at
68
+ <=:val levels\n Tag.enable :feature1, :feat2, ... # enables given features
69
+ on <=:trc\n Tag.enable :feature1, :feat2, feat3: :dtl, all: :err\n\t# Set :feature1,
70
+ :feat2, and :generic to <=:trc, :feat3 to :dtl\n\t# and ANY OTHER feature to only
71
+ :err. \n Tag.enable feature: :err \n Tag.enable feature: :dtl # so ALL
72
+ tags with feature :feature\n Tag.err(:feature) { raise 'aaaarg' if expensive_check_fails?
73
+ }\n"
74
+ email: eugenebrazwick@gmail.com
75
+ executables: []
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - lib/dbg_tags.rb
80
+ - spec/01_tag_spec.rb
81
+ homepage: https://github.com/Eugene-Brazwick/dbg_tags
82
+ licenses:
83
+ - GPL-3.0
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '2.7'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubygems_version: 3.1.2
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: a versatile dynamic debug tracing system
104
+ test_files:
105
+ - spec/01_tag_spec.rb