loba 0.3.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: b9de2bca8c9af5a371942f7ddf2f60d29cf6eaa7
4
- data.tar.gz: 463649f58af8da129580719b0d9cf9cf07ca1a4b
2
+ SHA256:
3
+ metadata.gz: e0f471467c64346c7c47d0b6496bf9f15677d8a2a107f8fe71dbf1901edd998d
4
+ data.tar.gz: b9c3ac98add22965ffcb61b3fcc9972d9144464690a70c78e66dd4f4b35483f9
5
5
  SHA512:
6
- metadata.gz: 8fa11f7116da2e56106805244ffed2b37f94f99a394d3391a3d39b689357a5708a76691f751ed4ad60ce1cc5b5cfab4d283a87a1b4d63b72ae6dcab7c94f0277
7
- data.tar.gz: 2bd9887db8c466e8bc2b8970014b67437045c472ce0a8ef3fab7cc49f9cfb53f8b8c876e29cd65911a31dad42490a8acea12b8936329827d43c488ccf89be19b
6
+ metadata.gz: a34112c0ce8214bc5dde3d5ad72bf1c457c954c0972b08d1fa0d43ff2d3b693b6db4a1d4ea4a86745712c5bb6d879f6cb885d1f3ac9453a50a4b2904c7eb3084
7
+ data.tar.gz: 85551529acd430a5e42849c87f76f2b811c63a038619b11f128e628f29f57d4ac86ddbface5eb878b5075b2920a6c5c5b467de4f9f25aeaa10991b3cdfe70cab
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015 Richard Newman
3
+ Copyright (c) 2015-2021 Richard Newman
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,5 +1,4 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/loba.svg)](https://badge.fury.io/rb/loba)
2
- [![Dependency Status](https://gemnasium.com/rdnewman/loba.svg)](https://gemnasium.com/rdnewman/loba)
3
2
  [![Build Status](https://travis-ci.org/rdnewman/loba.svg?branch=master)](https://travis-ci.org/rdnewman/loba)
4
3
  [![Code Climate](https://codeclimate.com/github/rdnewman/loba/badges/gpa.svg)](https://codeclimate.com/github/rdnewman/loba)
5
4
  [![Test Coverage](https://codeclimate.com/github/rdnewman/loba/badges/coverage.svg)](https://codeclimate.com/github/rdnewman/loba/coverage)
@@ -21,13 +20,13 @@ There are two kinds of questions I usually want to answer when trying to diagnos
21
20
  1. Is this spot of code being reached (or is it reached in the order I think it is)?
22
21
  1. What is the value of this variable?
23
22
 
24
- Loba statements are intended to be terse to minimize typing.
23
+ Loba statements are intended to be terse to minimize typing.
25
24
 
26
- Loba statements are intended to be minimally invasive and atomic. They should not have any (much) more impact than a regular `puts` or `Rails.logger.debug` statement.
25
+ Loba statements are intended to be minimally invasive and atomic. They should not have any (much) more impact than regular `puts` or `Rails.logger.debug` statements.
27
26
 
28
- Loba statements are expected to be removed when you're done with them. No point in cluttering up production code.
27
+ Loba statements are expected to be removed when you're done with them. No point in cluttering up production code.
29
28
 
30
- Loba will check for presence of Rails. If it's there, it'll write to `Rails.logger.debug`. If not, it'll write to STDOUT (i.e., `puts`). Loba will work equally well with or without Rails.
29
+ Loba will check for presence of Rails. If it's there, it'll write to `Rails.logger.debug`. If not, it'll write to STDOUT (i.e., `puts`). Loba will work equally well with or without Rails.
31
30
 
32
31
  Loba uses the [colorize gem](https://rubygems.org/gems/colorize) to help make trace statements more visible.
33
32
 
@@ -48,7 +47,7 @@ For example,
48
47
  To invoke,
49
48
 
50
49
  ```ruby
51
- Loba.ts # or with optional arguments
50
+ Loba.ts # or with optional keyword arguments
52
51
  ```
53
52
 
54
53
  `Loba.timestamp` is an alias for `Loba.ts`.
@@ -78,7 +77,7 @@ require 'loba' # not generally necessary in Rails projects
78
77
  class HelloWorld
79
78
  def initialize
80
79
  @x = 42
81
- Loba.ts # see? it's easier to see what to remove later
80
+ Loba.ts # Loba statement put to the far left as a reminder to remove when done
82
81
  @y = "Charlie"
83
82
  end
84
83
 
@@ -93,9 +92,9 @@ HelloWorld.new.hello
93
92
 
94
93
  Output:
95
94
 
96
- ```
95
+ ```
97
96
  [TIMESTAMP] #=0001, diff=0.000463, at=1451615389.505411 (in=/home/usracct/src/lobademo/hello_world.rb:4:in 'initialize'
98
- [HelloWorld#hello] @x: 42 (in /home/richard/src/loba/spec/hello_world.rb:9:in `hello')
97
+ [HelloWorld#hello] @x: 42 (in /home/usracct/src/loba/spec/hello_world.rb:9:in `hello')
99
98
  Hello, Charlie
100
99
  [TIMESTAMP] #=0002, diff=0.000720, at=1451615389.506132 (in=/home/usracct/src/lobademo/hello_world.rb:11:in 'hello'
101
100
  ```
@@ -106,9 +105,14 @@ This section is only relevant in Rails environments.
106
105
 
107
106
  The expectation is that Loba statements are just for development or test trace statements. Generally, it's a bad idea to leave diagnostic code in Rails production; still, it can happen. And, occasionally, it can be useful to have trace statements in production too if you have an issue that is difficult to reproduce.
108
107
 
109
- `Loba.ts` and `Loba.val` try to protect against timestamp or value notice requests being accidentally left in the code by checking for the Rails environment Loba is being invoked under. If in production, `Loba.ts` and `Loba.val` will normally just return immediately without rendering anything to help minimize any impact on production code. However, that behavior can be overridden by using the options hash with `:production => true` as an additional last argument to output a notice even when in the production environment. In general, this should be done sparingly if at all.
108
+ `Loba.ts` and `Loba.val` try to protect against timestamp or value notice requests being accidentally left in the code by checking for the Rails environment Loba is being invoked under. If in production, `Loba.ts` and `Loba.val` will normally just return immediately without attempting to render anything to help minimize any impact on production code.
109
+
110
+ However, that behavior can be overridden by using the options hash with `:production => true` as an additional last argument to output a notice even when in the production environment. In general, this should be avoided.
110
111
 
111
- These considerations also have an impact on how you install the Loba gem when using `bundler`. If you only install the gem for :development and :test, then any Loba statements left in the code when it goes to production will cause an error because the statements wouldn't be recognized. That's perhaps a Good Thing, if you never want them left in.
112
+ WARNING: this gem depends on the [binding_of_caller gem](https://rubygems.org/gems/binding_of_caller) -- use `:production => true` with their warning in mind:
113
+ > **Recommended for use only in debugging situations. Do not use this in production apps.**
114
+
115
+ These considerations also have an impact on how you install the Loba gem when using `bundler`. If you only install the gem for :development and :test, then any Loba statements left in the code when it goes to production will cause an error because the statements wouldn't be recognized. That's usually a Good Thing, if you never want them left in.
112
116
 
113
117
  If you simply install the gem for all environments, then Loba will be available in production, but you may not notice as easily if some Loba calls are unintentionally left in. Of course, if you want those statements to work in production, then you should install the gem for all environments.
114
118
 
@@ -123,7 +127,7 @@ Loba.ts production: true
123
127
  end
124
128
 
125
129
  def hello
126
- Loba.val :@x, nil, production: true
130
+ Loba.val :@x, production: true
127
131
  puts "Hello, #{@y}" if @x == 42
128
132
  Loba.ts true
129
133
  end
@@ -135,7 +139,14 @@ HelloWorld.new.hello
135
139
 
136
140
  See above Environment Notes if using with Rails.
137
141
 
138
- Add this line to your application's Gemfile:
142
+
143
+ Install as below to be generally available (recommended to restrict to only local use):
144
+
145
+ ```bash
146
+ $ gem install loba
147
+ ```
148
+
149
+ To bundle, add this line to your application's Gemfile:
139
150
 
140
151
  ```ruby
141
152
  group :development, :test do
@@ -143,7 +154,7 @@ group :development, :test do
143
154
  end
144
155
  ```
145
156
 
146
- or for all environments:
157
+ or for all environments (for example, if `production: true` used):
147
158
 
148
159
  ```ruby
149
160
  gem 'loba', require: false
@@ -156,12 +167,6 @@ And then execute:
156
167
  $ bundle
157
168
  ```
158
169
 
159
- Or install it yourself as:
160
-
161
- ```bash
162
- $ gem install loba
163
- ```
164
-
165
170
  ## Development
166
171
 
167
172
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -171,6 +176,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
171
176
  ## Changelog
172
177
  |version|notes|
173
178
  |-------|-----|
179
+ |1.0.0|updated for more recent rubies; uses Ruby 2.x-style keyword arguments for specifying options|
174
180
  |0.3.1|updated dependences; added inspect to Loba.val; amended parameters*|
175
181
  |0.3.0|(yanked)|
176
182
  |0.2.0|release on RubyGems.org|
@@ -178,8 +184,11 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
178
184
 
179
185
  ### Deprecations
180
186
 
187
+ #### 1.0.0
188
+ In v0.3.x, to allow Loba notes to write to the log while in :production, an options hash as `{:production => true}` was introduced; this is now specified directly via Ruby-2.x style keywords, e.g., `production: true`. THIS IS A BREAKING CHANGE FROM v0.3.1 and earlier versions.
189
+
181
190
  #### 0.3.0
182
- In prior versions, to allow Loba notes to write to the log while in :production, an optional third parameter could be supplied as merely a boolean value. In 0.3.0 and later versions, this must now be specified as part of an options hash as `{:production => true}`
191
+ In prior versions, to allow Loba notes to write to the log while in :production, an optional third argument could be supplied as merely a boolean value. In 0.3.0 and later versions, this must now be specified as part of an options hash as `{:production => true}`
183
192
 
184
193
  ### Semantic versions
185
194
 
data/lib/loba.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'loba/version'
2
+ require 'loba/internal'
2
3
 
3
- require 'singleton'
4
4
  require 'binding_of_caller'
5
5
  require 'colorize'
6
6
 
@@ -8,66 +8,65 @@ require 'colorize'
8
8
  # If a Rails application, will use Rails.logger.debug.
9
9
  # If not a Rails application, will use STDOUT.
10
10
  module Loba
11
-
12
11
  # Outputs a timestamped notice, useful for quick traces to see the code path.
13
- # Also does a simple elapsed time check since the previous timestamp notice to help with quick, minimalist profiling.
14
- # @param options [Hash] options for use
15
- # @option options [Boolean] :production (false) true if this timestamp notice is enabled when running in :production environment
12
+ # Also does a simple elapsed time check since the previous timestamp notice to
13
+ # help with quick, minimalist profiling.
14
+ # @param production [Boolean] set to true if this timestamp notice is
15
+ # to be recorded when running in :production environment
16
16
  # @return [NilClass] nil
17
17
  # @example Basic use
18
18
  # def hello
19
- # Loba.ts
19
+ # Loba.timestamp
20
20
  # end
21
21
  # #=> [TIMESTAMP] #=0001, diff=0.000463, at=1451615389.505411, in=/path/to/file.rb:2:in 'hello'
22
- def ts(options = {})
23
-
24
- # evaluate options
25
- filtered_options = Internal.filter_options(options, [:production])
26
- production_is_ok = filtered_options[:production]
27
-
28
- # log if possible
29
- if Internal::Platform.logging_ok?(production_is_ok)
30
- @loba_logger ||= Internal::Platform.logger
31
- @loba_timer ||= Internal::TimeKeeper.instance
32
-
33
- begin
34
- @loba_timer.timenum += 1
35
- timenow = Time.now()
36
- stamptag = '%04d'%(@loba_timer.timenum)
37
- timemark = '%.6f'%(timenow.round(6).to_f)
38
- timechg = '%.6f'%(timenow - @loba_timer.timewas)
39
- @loba_logger.call "[TIMESTAMP]".black.on_light_black +
40
- " #=".yellow +
41
- "#{stamptag}" +
42
- ", diff=".yellow +
43
- "#{timechg}" +
44
- ", at=".yellow +
45
- "#{timemark}" +
46
- " \t(in=#{caller[0]})".light_black
47
- @loba_timer.timewas = timenow
48
- rescue StandardError => e
49
- @loba_logger.call "[TIMESTAMP] #=FAIL, in=#{caller[0]}, err=#{e}".colorize(:red)
50
- end
22
+ # @example Forced to output when in production environment
23
+ # def hello
24
+ # Loba.ts production: true # Loba.ts is a shorthand alias for Loba.timestamp
25
+ # end
26
+ # #=> [TIMESTAMP] #=0001, diff=0.000463, at=1451615389.505411, in=/path/to/file.rb:2:in 'hello'
27
+ def timestamp(production: false)
28
+ return unless Internal::Platform.logging_ok?(production)
29
+
30
+ # produce timestamp notice
31
+ @loba_logger ||= Internal::Platform.logger
32
+
33
+ begin
34
+ stats = Internal::TimeKeeper.instance.ping
35
+ @loba_logger.call '[TIMESTAMP]'.black.on_light_black +
36
+ ' #='.yellow +
37
+ format('%04d', stats[:number]).to_s +
38
+ ', diff='.yellow +
39
+ format('%.6f', stats[:change]).to_s +
40
+ ', at='.yellow +
41
+ format('%.6f', stats[:now].round(6).to_f).to_s +
42
+ " \t(in=#{caller(1..1).first})".light_black
43
+ rescue StandardError => e
44
+ @loba_logger.call "[TIMESTAMP] #=FAIL, in=#{caller(1..1).first}, err=#{e}".colorize(:red)
51
45
  end
46
+
52
47
  nil
53
48
  end
54
- module_function :ts
55
-
56
- # Alias for Loba.ts
57
- alias_method :timestamp, :ts
58
49
  module_function :timestamp
59
50
 
60
- # Outputs a value notice showing value of provided argument including method and class identification
61
- # @param argument [various] the value to be evaluated and shown; if given as a Symbol, a label based on the argument will proceed the value the argument refers to
62
- # @param label [String] an optional, explicit label to be used instead of attempting to infer from the argument
63
- # @param options [Hash] options for use
64
- # @option options [Boolean] :inspect (true) true if this value notice is to use #inspect against the content being evaluated
65
- # @option options [Boolean] :production (false) true if this value notice is enabled when running in :production environment
51
+ # Shorthand alias for Loba.timestamp.
52
+ alias ts timestamp
53
+ module_function :ts
54
+
55
+ # Outputs a value notice showing value of provided argument including method and
56
+ # class identification.
57
+ # @param argument [various] (required) the value to be evaluated and shown; if given as
58
+ # a Symbol, a label based on the argument will proceed the value the argument refers to
59
+ # @param label [String] explicit label to be used instead of attempting
60
+ # to infer from the argument; default is to attempt to infer a label from the argument
61
+ # @param inspect [Boolean] true if this value notice is to use #inspect against the
62
+ # content being evaluated; otherwise, false
63
+ # @param production [Boolean] set to true if this timestamp notice is
64
+ # to be recorded when running in :production environment
66
65
  # @return [NilClass] nil
67
66
  # @example Using Symbol as argument
68
67
  # class HelloWorld
69
68
  # def hello(name)
70
- # Loba.val :name # best to put Loba statement to far left for easy removal when done
69
+ # Loba.value :name # putting Loba statement to far left helps remember to remove later
71
70
  # puts "Hello, #{name}!"
72
71
  # end
73
72
  # end
@@ -77,7 +76,7 @@ module Loba
77
76
  # @example Using non-Symbol as argument
78
77
  # class HelloWorld
79
78
  # def hello(name)
80
- # Loba.val name
79
+ # Loba.val name # Loba.val is a shorthand alias for Loba.value
81
80
  # puts "Hello, #{name}!"
82
81
  # end
83
82
  # end
@@ -87,194 +86,34 @@ module Loba
87
86
  # @example Using non-Symbol as argument with a label
88
87
  # class HelloWorld
89
88
  # def hello(name)
90
- # Loba.val name, "Name:"
89
+ # Loba.value name, "Name:"
91
90
  # puts "Hello, #{name}!"
92
91
  # end
93
92
  # end
94
93
  # HelloWorld.new.hello("Charlie")
95
94
  # #=> [HelloWorld#hello] Name: Charlie (at /path/to/file/hello_world.rb:3:in `hello')
96
95
  # #=> Hello, Charlie!
97
- def val(argument = :nil, label = nil, options = {inspect: true})
98
-
99
- # evaluate options
100
- filtered_options = Internal.filter_options(options, [:production, :inspect])
101
- production_is_ok = filtered_options[:production]
102
- will_inspect = filtered_options[:inspect]
103
-
104
- # log if possible
105
- if Internal::Platform.logging_ok?(production_is_ok)
106
- depth = 0
107
- @loba_logger ||= Internal::Platform.logger
108
-
109
- tag = Internal.calling_tag(depth+1)
110
- name = argument.is_a?(Symbol) ? "#{argument}:" : nil
111
-
112
- text = if label.nil?
113
- name
114
- else
115
- label.strip!
116
- label += ':' unless label[-1] == ':'
117
- end
118
-
119
- result = if argument.is_a?(Symbol)
120
- if will_inspect
121
- binding.of_caller(depth+1).eval(argument.to_s).inspect
122
- else
123
- binding.of_caller(depth+1).eval(argument.to_s)
124
- end
125
- else
126
- will_inspect ? argument.inspect : argument
127
- end
96
+ def value(argument, label: nil, inspect: true, production: false)
97
+ return nil unless Internal::Platform.logging_ok?(production)
98
+
99
+ @loba_logger ||= Internal::Platform.logger
100
+
101
+ text = Internal::Value.phrases(
102
+ argument: (argument.nil? ? :nil : argument),
103
+ label: label,
104
+ inspect: inspect,
105
+ depth_offset: 1
106
+ )
107
+ @loba_logger.call "#{text[:tag]} ".green +
108
+ "#{text[:label]} ".light_green +
109
+ text[:value] +
110
+ " \t(in #{text[:line]})".light_black
128
111
 
129
- source_line = Internal.calling_source_line(depth+1)
130
-
131
- @loba_logger.call "#{tag} ".green +
132
- "#{text.nil? ? '' : "#{text}"} ".light_green +
133
- "#{result.nil? ? '-nil-' : result}" +
134
- " \t(in #{source_line})".light_black
135
- end
136
112
  nil
137
113
  end
138
- module_function :val
139
-
140
-
141
- module Internal
114
+ module_function :value
142
115
 
143
- class << self
144
-
145
- # Prepare display of class name from where Loba was invoked
146
- # @param depth [integer] internal tracking of call stack depth
147
- def calling_class_name(depth = 0)
148
- m = binding.of_caller(depth+1).eval('self.class.name')
149
- if m.nil? || m.empty?
150
- '<anonymous class>'
151
- elsif m == 'Class'
152
- binding.of_caller(depth+1).eval('self.name')
153
- else
154
- m
155
- end
156
- end
157
-
158
- # Prepare display of method name from where Loba was invoked
159
- # @param depth [integer] internal tracking of call stack depth
160
- def calling_method_name(depth = 0)
161
- m = binding.of_caller(depth+1).eval('self.send(:__method__)')
162
- (m.nil? || m.empty?) ? '<anonymous method>' : m
163
- end
164
-
165
- # Prepare display of whether the method from where Loba was invoked is for a class or an instance
166
- # @param depth [integer] internal tracking of call stack depth
167
- def calling_method_type(depth = 0)
168
- if binding.of_caller(depth+1).eval('self.class.name') == 'Class'
169
- :class
170
- else
171
- :instance
172
- end
173
- end
174
-
175
- # Prepare display of line number from where Loba was invoked [UNUSED]
176
- # @param depth [integer] internal tracking of call stack depth
177
- def calling_line_number(depth = 0)
178
- binding.of_caller(depth+1).eval('__LINE__')
179
- end
180
-
181
- # Assemble display that shows the method invoking Loba
182
- # @param depth [integer] internal tracking of call stack depth
183
- def calling_tag(depth = 0)
184
- delim = {class: '.', instance: '#'}
185
- "[#{calling_class_name(depth+1)}#{delim[calling_method_type(depth+1)]}#{calling_method_name(depth+1)}]"
186
- end
187
-
188
- # Identify source code line from where Loba was invoked
189
- # @param depth [integer] internal tracking of call stack depth
190
- def calling_source_line(depth = 0)
191
- caller[depth]
192
- end
193
-
194
- # Filters options argument for deprecated or unexpected use
195
- # @param options [various] options argument to filter
196
- # @param allowed_keys [array] array of expected keys in options
197
- def filter_options(options, allowed_keys = [])
198
- result = {}
199
- allowed_keys.each { |key| result[key] = false }
200
-
201
- case options
202
- when Hash
203
- allowed_keys.each do |key|
204
- result[key] = !!options[key] unless options[key].nil?
205
- end
206
- when TrueClass
207
- if allowed_keys.include? :production
208
- Internal::Deprecated._0_3_0(true)
209
- result[:production] = true
210
- end
211
- when FalseClass
212
- Internal::Deprecated._0_3_0(false)
213
- else # to be safe, treat as false
214
- Internal::Deprecated._0_3_0(false)
215
- end
216
-
217
- result
218
- end
219
-
220
- end
221
-
222
- # Internal class for deprecation warnings.
223
- class Deprecated
224
- class << self
225
- # Deprecations as of version 0.3.0
226
- # @param value [boolean] deprecated value supplied in original call to use in deprecation message
227
- def _0_3_0(value)
228
- bool = value ? "true" : "false"
229
- verb = value ? "enabled" : "disabled"
230
- warn "DEPRECATION WARNING: use {:production => #{bool}} instead to indicate notice is #{verb} in production"
231
- end
232
- end
233
- end
234
-
235
- # Internal class for tracking time stamps; should not be used directly
236
- # @!attribute [rw] timewas
237
- # Previous timestamped Time value
238
- # @!attribute [rw] timenum
239
- # Count of timestamping occurances so far
240
- class TimeKeeper
241
- include Singleton
242
- attr_accessor :timewas, :timenum
243
- def initialize
244
- @timewas, @timenum = Time.now, 0
245
- end
246
- end
247
-
248
- # Internal class for managing logging across Rails and non-Rails applications
249
- class Platform
250
- class << self
251
- # Returns true if Rails appears to be available
252
- def rails?
253
- defined?(Rails)
254
- end
255
-
256
- # Returns true if logging is to be allowed
257
- def logging_ok?(force_true = false)
258
- return true if force_true
259
- return true unless rails?
260
- begin
261
- !Rails.env.production?
262
- rescue
263
- true # not Rails production if Rails isn't recognized
264
- end
265
- end
266
-
267
- # Returns a logging mechanism appropriate for the application
268
- def logger
269
- if (rails? && Rails.logger.present?)
270
- ->(arg){Rails.logger.debug arg}
271
- else
272
- ->(arg){puts arg}
273
- end
274
- end
275
- end
276
- end
277
-
278
- end # module Internal
279
-
280
- end # module Loba
116
+ # Shorthand alias for Loba.value.
117
+ alias val value
118
+ module_function :val
119
+ end