nrser 0.3.5 → 0.3.6

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: e9a0b7b61d0a481af1ca35a8eb86e7ab13aff165
4
- data.tar.gz: e7c16292a7f5ccfa34ce0e490a7f91313f9e34e5
3
+ metadata.gz: c4c0b136095e4afd7f800b70365fef71ab0d6aa8
4
+ data.tar.gz: 0e7ae07d35167aef235790e048469175e278678d
5
5
  SHA512:
6
- metadata.gz: e085701c29d0a89e2983734e8a2d120fe1d03248cf2d8bf5644761f1e00c5fd8d20bcf676a09785b312cb85c81cd1203330d5011ffcf956916f95dae3cdec16f
7
- data.tar.gz: 68bd8090335751c9ee51f2026c33d23acecdb4faad507b89879fe036fb3758f79a3ba934682a26a6613601ce36b129bd3048ee62613b8751e0089f0d32cf4b58
6
+ metadata.gz: dca7159d865ba58bb26a0fe3a24f4cdab90c09416509cc7f7d466aad6c5a23dd5fa6f5f0d35b4adb9a6d2e93c9ea52f03f8f63b03f237e5e3cabc3374f258d5f
7
+ data.tar.gz: 4de1a2e02822d68a529f37ce1bcf53f25c4f8100284fb841c3bf254509d0f0a85adacdc823c1a857da5de7f0d8c9911214bc3e1ab4984d576a468aaba3646d75
@@ -64,39 +64,161 @@ class NRSER::Log::Logger < SemanticLogger::Logger
64
64
  end # class Catcher
65
65
 
66
66
 
67
- class Notifier
68
-
69
- # Construction
70
- # ========================================================================
71
-
72
- # Instantiate a new `Notifier`.
73
- #
74
- # @param [NRSER::Log::Logger] logger
75
- # The logger to use if the block raises.
76
- #
77
- # @param [*] on_fail:
78
- # Value to return when `&block` raises.
79
- #
80
- def initialize logger
81
- @logger = logger
82
- end # #initialize
67
+ # Under JRuby a java exception is not a Ruby Exception
68
+ #
69
+ # Java::JavaLang::ClassCastException.new.is_a?(Exception) => false
70
+ #
71
+ def self.is_exception? value
72
+ value.is_a?( Exception) ||
73
+ [:backtrace, :message].all? { |name| value.respond_to? name }
74
+ end
75
+
76
+
77
+ # Normalizes the valid argument formats to {SemanticLogger::Logger}'s
78
+ # "standard logging methods" into a keywords hash.
79
+ #
80
+ # By "standard logging methods", we mean {SemanticLogger::Logger#debug},
81
+ # {SemanticLogger::Logger#info}, etc., as detailed in the
82
+ # [Semantic Logger API][] documentation.
83
+ #
84
+ # [Semantic Logger API]: https://rocketjob.github.io/semantic_logger/api.html
85
+ #
86
+ # Semantic Logger documents the standard logging methods API as
87
+ #
88
+ # log.info(message, payload_or_exception = nil, exception = nil, &block)
89
+ #
90
+ # or
91
+ #
92
+ # logger.info(
93
+ # message: String?,
94
+ # payload: Hash?,
95
+ # exception: Object?,
96
+ # **metric_keywords
97
+ # )
98
+ #
99
+ # Which means that the hash returned by this method can be used as the
100
+ # argument to the standard logging methods:
101
+ #
102
+ # def proxy_info_call *args, &block
103
+ # logger.info **NRSER::Log::Logger.args_to_kwds( *args ), &block
104
+ # end
105
+ #
106
+ # This makes this method very useful when pre-processing log call arguments,
107
+ # as is done in {NRSER::Log::Plugin} before passing the resulting keywords
108
+ # to {NRSER::Log::Plugin#call} because the hash this method returns is much
109
+ # easier to work with than the standard logging methods' multiple valid
110
+ # argument formats.
111
+ #
112
+ # @param [Array] *args
113
+ # Valid arguments for {SemanticLogger::Logger#debug}, etc. - see notes
114
+ # above.
115
+ #
116
+ # @return [Hash<Symbol, Object>]
117
+ # Always has the following keys (**all** of which can have `nil` value):
118
+ #
119
+ # - `message: String?` - we don't actually check that it's a {String},
120
+ # but that seems to be pretty much what Semantic Logger expects.
121
+ #
122
+ # - `payload: Hash?` - A hash of names to values to log. By convention
123
+ # names are {Symbol}, though I'm not sure what happens if they are not.
124
+ #
125
+ # - `exception: Object?` - An error to log. This will be an {Exception}
126
+ # in MRI. In JRuby, and perhaps elsewhere, they won't be, but they
127
+ # should always respond to `#message` and `#backtrace`.
128
+ #
129
+ # - `metric: Object?` -
130
+ #
131
+ def self.args_to_kwds *args
132
+ log_kwds = {
133
+ message: nil,
134
+ payload: nil,
135
+ exception: nil,
136
+ metric: nil,
137
+ }
83
138
 
139
+ case args.length
140
+ when 0
141
+ # pass - they all stay `nil` (which it seems SemLog allows, so we'll
142
+ # stick to it)
84
143
 
85
- # Instance Methods
86
- # ========================================================================
144
+ when 1
145
+ case args[0]
146
+ when Hash
147
+ if [:message, :payload, :exception, :metric].
148
+ any? { |key| args[0].key? key }
149
+ log_kwds = args[0]
150
+ else
151
+ # It's the payload
152
+ log_kwds[:payload] = args[0]
153
+ end
154
+ else
155
+ if is_exception? args[0]
156
+ # It's the exception
157
+ log_kwds[:exception] = args[0]
158
+ else
159
+ # It's got to be the message
160
+ log_kwds[:message] = args[0]
161
+ end
162
+ end
87
163
 
88
- SemanticLogger::LEVELS.each do |level|
89
- define_method level do |message = nil, payload = nil, &block|
90
- begin
91
- block.call
92
- rescue Exception => error
93
- @logger.send level, message, payload, error
94
- @on_fail
164
+ when 2
165
+ if args[0].is_a? Hash
166
+ log_kwds[:payload] = args[0]
167
+ log_kwds[:exception] = args[1]
168
+ else
169
+ log_kwds[:message] = args[0]
170
+
171
+ if args[1].is_a? Hash
172
+ log_kwds[:payload] = args[1]
173
+ else
174
+ log_kwds[:exception] = args[1]
95
175
  end
96
176
  end
177
+
178
+ when 3
179
+ log_kwds[:message] = args[0]
180
+ log_kwds[:payload] = args[1]
181
+ log_kwds[:exception] = args[2]
182
+
183
+ else
184
+ raise NRSER::ArgumentError.new \
185
+ "Too many args dude - max 3",
186
+ args: args
187
+
97
188
  end
98
189
 
99
- end
190
+ log_kwds
191
+
192
+ end # .normalize_log_args
193
+
194
+
195
+ # Install a plugin, dynamically adding it's
196
+ # {NRSER::Log::Plugin.method_name} instance method.
197
+ #
198
+ # @param [Class<NRSER::Log::Plugin>] plugin_class
199
+ # The plugin class to add.
200
+ #
201
+ # @return [nil]
202
+ #
203
+ # @raise [NRSER::ConflictError]
204
+ # If this class already has an instance method defined with the name
205
+ # returned from `plugin_class.method_name`.
206
+ #
207
+ def self.plugin plugin_class
208
+ method_name = plugin_class.method_name
209
+
210
+ if instance_methods.include? method_name.to_sym
211
+ raise NRSER::ConflictError.new \
212
+ "Can not install", plugin_class.safe_name,
213
+ "Logger plugin: instance method", method_name, "already defined"
214
+ end
215
+
216
+ define_method method_name do |*args, &block|
217
+ plugin_class.new self, *args, &block
218
+ end
219
+
220
+ nil
221
+ end # .plugin
100
222
 
101
223
 
102
224
  # Attributes
@@ -185,6 +307,41 @@ class NRSER::Log::Logger < SemanticLogger::Logger
185
307
  # Instance Methods
186
308
  # ========================================================================
187
309
 
310
+ # Log message at the specified level
311
+ def build_log level,
312
+ index,
313
+ message = nil,
314
+ payload = nil,
315
+ exception = nil,
316
+ &block
317
+ log = SemanticLogger::Log.new name, level, index
318
+ should_log =
319
+ if payload.nil? && exception.nil? && message.is_a?( Hash )
320
+ # Check if someone just logged a hash payload instead of meaning to call semantic logger
321
+ if message.key?( :message ) ||
322
+ message.key?( :payload ) ||
323
+ message.key?( :exception ) ||
324
+ message.key?( :metric )
325
+ log.assign message
326
+ else
327
+ log.assign_positional nil, message, nil, &block
328
+ end
329
+ else
330
+ log.assign_positional message, payload, exception, &block
331
+ end
332
+
333
+ # Log level may change during assign due to :on_exception_level
334
+ [ log, should_log && should_log?( log ) ]
335
+ end
336
+
337
+
338
+ # Log message at the specified level
339
+ # def log_internal *args, &block
340
+ # log, should_log = build_log *args
341
+ # self.log( log ) if should_log
342
+ # end
343
+
344
+
188
345
  # A sweet way to try something and just log any {Exception}.
189
346
  #
190
347
  # Useful for situations where the operation is question is not necessary
@@ -0,0 +1,153 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Deps
8
+ # -----------------------------------------------------------------------
9
+
10
+ # Need {SemanticLogger::Logger}
11
+ require 'semantic_logger'
12
+
13
+
14
+ # Refinements
15
+ # =======================================================================
16
+
17
+
18
+ # Namespace
19
+ # =======================================================================
20
+
21
+ module NRSER
22
+ module Log
23
+
24
+
25
+ # Definitions
26
+ # =======================================================================
27
+
28
+ # Abstract base class that wraps a {NRSER::Log::Logger} and exposes the
29
+ # level logging methods - `#debug`, `#info`, etc. - routing those calls
30
+ # through it's {#call} method and on to the logger's method, allowing
31
+ # concrete subclasses to hook into those calls and provide additional
32
+ # functionality and logic.
33
+ #
34
+ # Convention is
35
+ #
36
+ # @abstract
37
+ #
38
+ # @see NRSER::Log::Logger::Catcher
39
+ # @see NRSER::Log::Logger::Notifier
40
+ #
41
+ # @todo
42
+ # Make plugins "stackable".
43
+ #
44
+ # Not sure if this example in particular would make any sense, but you can
45
+ # get the idea:
46
+ #
47
+ # logger.notify.catcher.warn
48
+ #
49
+ class Plugin
50
+
51
+ # Class Methods
52
+ # ========================================================================
53
+
54
+ # The {NRSER::Log::Logger} method name that will create plugin instances.
55
+ #
56
+ # Looks for the `@method_name` class instance variable, and defaults to
57
+ # `safe_name.demodulize.underscore` if that is not found.
58
+ #
59
+ # @return [Symbol | String]
60
+ #
61
+ def self.method_name
62
+ @method_name || safe_name.demodulize.underscore
63
+ end # .method_name
64
+
65
+
66
+ # Attributes
67
+ # ========================================================================
68
+
69
+ # The wrapped logger instance.
70
+ #
71
+ # @return [NRSER::Log::Logger]
72
+ #
73
+ attr_reader :logger
74
+
75
+
76
+ # Construction
77
+ # ========================================================================
78
+
79
+ # Instantiate a new plugin instance.
80
+ #
81
+ # @param [NRSER::Log::Logger] logger
82
+ # The wrapper logger instance.
83
+ #
84
+ def initialize logger
85
+ @logger = logger
86
+ end # #initialize
87
+
88
+
89
+ # Instance Methods
90
+ # ========================================================================
91
+
92
+ # This is where realizing subclasses can hook into log calls.
93
+ #
94
+ # This base implementation just calls the `level` method on {#logger}
95
+ # with the `args` and `block`.
96
+ #
97
+ # @note
98
+ # Though the logging methods don't use a block at this time, it's there
99
+ # for completeness and possible futures.
100
+ #
101
+ # @param [Symbol] level:
102
+ # The log level of the call; one of {SemanticLogger::LEVELS}.
103
+ #
104
+ # @param [String?] message:
105
+ # Log message.
106
+ #
107
+ # @param [Hash?] payload:
108
+ # Map of names to values to log.
109
+ #
110
+ # @param [Object?] exception:
111
+ # An error to log. This will be an {Exception} in MRI, but *won't* be in
112
+ # JRuby and possibly other runtimes.
113
+ #
114
+ # @param [Object?] metric:
115
+ # I don't know what this is. I found it in the SemLog code.
116
+ #
117
+ # @param [Proc] &block
118
+ # Block to pass to the {#logger}'s `level` method. Not currently used
119
+ # (see note above).
120
+ #
121
+ def call level:, message:, payload:, exception:, metric:, &block
122
+ logger.send \
123
+ level,
124
+ message: message,
125
+ payload: payload,
126
+ exception: exception,
127
+ metric: metric,
128
+ &block
129
+ end
130
+
131
+
132
+ # Dynamically define each logging method.
133
+ SemanticLogger::LEVELS.each do |level|
134
+ define_method level do |*args, &block|
135
+ call level: level, **NRSER::Log::Logger.args_to_kwds( *args ), &block
136
+ end
137
+ end
138
+
139
+
140
+ # @return [String]
141
+ # Short string description of the instance.
142
+ def to_s
143
+ "#<#{ self.class.safe_name } #{ logger }>"
144
+ end
145
+
146
+ end # class Plugin
147
+
148
+
149
+ # /Namespace
150
+ # =======================================================================
151
+
152
+ end # module Log
153
+ end # module NRSER
@@ -1,7 +1,4 @@
1
- require 'nrser/refinements'
2
1
  require 'nrser/types/type'
3
-
4
- using NRSER
5
2
 
6
3
  module NRSER::Types
7
4
  class Bounded < NRSER::Types::Type
@@ -1,6 +1,4 @@
1
- require 'nrser/refinements'
2
1
  require 'nrser/types/type'
3
- using NRSER
4
2
 
5
3
  module NRSER::Types
6
4
  # Type satisfied by class membership (or mixin presence for modules).
@@ -1,10 +1,8 @@
1
- require 'nrser/refinements'
2
1
  require 'nrser/types/type'
3
2
  require 'nrser/types/is_a'
4
3
  require 'nrser/types/combinators'
5
4
  require 'nrser/types/bounded'
6
5
 
7
- using NRSER
8
6
 
9
7
  module NRSER::Types
10
8
  # Parse a string into a number.
data/lib/nrser/version.rb CHANGED
@@ -18,7 +18,7 @@ module NRSER
18
18
  #
19
19
  # @return [String]
20
20
  #
21
- VERSION = '0.3.5'
21
+ VERSION = '0.3.6'
22
22
 
23
23
 
24
24
  module Version
@@ -1,9 +1,3 @@
1
- require 'spec_helper'
2
-
3
- require 'nrser/refinements'
4
- using NRSER
5
-
6
-
7
1
  # NRSER.merge_by
8
2
  # ========================================================================
9
3
  #
@@ -1,8 +1,3 @@
1
- require 'spec_helper'
2
-
3
- require 'nrser/refinements'
4
- using NRSER
5
-
6
1
  describe "NRSER.each_branch" do
7
2
 
8
3
  subject { NRSER.method :each_branch }
@@ -65,7 +60,7 @@ describe "NRSER.each_branch" do
65
60
  input = [:x, :y, :z]
66
61
  result = {}
67
62
  super().call( input ) { |index, value|
68
- result[index] = value
63
+ result[index] = value
69
64
  }
70
65
  result
71
66
  }
@@ -79,4 +74,3 @@ describe "NRSER.each_branch" do
79
74
  end # called with a block
80
75
 
81
76
  end # NRSER.each_branch
82
-
@@ -1,8 +1,3 @@
1
- require 'spec_helper'
2
-
3
- require 'nrser/refinements'
4
- using NRSER
5
-
6
1
  describe "NRSER.map_branches" do
7
2
  # ========================================================================
8
3
 
@@ -1,8 +1,3 @@
1
- require 'spec_helper'
2
-
3
- require 'nrser/refinements'
4
- using NRSER
5
-
6
1
  describe_method "NRSER.map_tree" do
7
2
  # ========================================================================
8
3
 
@@ -1,8 +1,3 @@
1
- require 'spec_helper'
2
-
3
- require 'nrser/refinements'
4
- using NRSER
5
-
6
1
  describe "NRSER.transform" do
7
2
  subject { NRSER.transform tree, source }
8
3
 
@@ -1,10 +1,3 @@
1
- # Refinements
2
- # =======================================================================
3
-
4
- require 'nrser/refinements'
5
- using NRSER
6
-
7
-
8
1
  # Examples
9
2
  # =====================================================================
10
3
 
@@ -135,7 +128,7 @@ describe_method "NRSER.transformer" do
135
128
  users: {
136
129
  { contact_id: address.parent.id } => {
137
130
  addresses: {
138
- {
131
+ {
139
132
  address_id: address.id } => {
140
133
  district: address[:address],
141
134
  line_1: address[:street2],
@@ -176,4 +169,3 @@ describe_method "NRSER.transformer" do
176
169
 
177
170
 
178
171
  end # NRSER.transform
179
-
@@ -1,8 +1,3 @@
1
- require 'spec_helper'
2
-
3
- require 'nrser/refinements'
4
- using NRSER
5
-
6
1
  require 'nrser/refinements/types'
7
2
  using NRSER::Types
8
3
 
@@ -18,13 +13,13 @@ describe NRSER::Message, type: :class do
18
13
 
19
14
  describe_called_with NRSER::Message.new( :length ) do
20
15
  it { is_expected.to eq [0, 1, 2] }
21
- end # called with
16
+ end # called with
22
17
 
23
18
  describe_called_with NRSER::Message.new( :first ) do
24
19
  it { is_expected.to eq [nil, 1, 1] }
25
20
  end # called with :first
26
21
 
27
- end # enum
22
+ end # enum
28
23
 
29
24
  end # mapping an Enumerable using &message
30
25
 
@@ -1,11 +1,6 @@
1
- require 'spec_helper'
2
- require 'nrser/refinements'
3
-
4
- using NRSER
5
-
6
1
  describe "NRSER.format_exception" do
7
2
  let(:error) {
8
- begin
3
+ begin
9
4
  raise StandardError.new "blah blah blah"
10
5
  rescue Exception => e
11
6
  e
@@ -17,4 +12,4 @@ describe "NRSER.format_exception" do
17
12
  expect( str ).to start_with "blah blah blah (StandardError):"
18
13
  expect( str.lines.drop(1) ).to all( start_with ' ' )
19
14
  end
20
- end
15
+ end
@@ -1,8 +1,3 @@
1
- require 'spec_helper'
2
- require 'nrser/refinements'
3
-
4
- using NRSER
5
-
6
1
  describe "NRSER.indent" do
7
2
  it "refines String to add indent" do
8
3
  expect(
@@ -1,8 +1,3 @@
1
- require 'spec_helper'
2
- require 'nrser/refinements'
3
-
4
- using NRSER
5
-
6
1
  describe 'Pathname' do
7
2
 
8
3
  describe '#start_with?' do
@@ -1,8 +1,3 @@
1
- require 'spec_helper'
2
-
3
- require 'nrser/refinements'
4
- using NRSER
5
-
6
1
  require 'nrser/refinements/types'
7
2
  using NRSER::Types
8
3
 
@@ -38,4 +33,3 @@ describe "NRSER::Types.hash_pair" do
38
33
  end # NRSER::Types.hash_pair
39
34
 
40
35
  # ************************************************************************
41
-
@@ -1,8 +1,3 @@
1
- require 'spec_helper'
2
-
3
- require 'nrser/refinements'
4
- using NRSER
5
-
6
1
  require 'nrser/refinements/types'
7
2
  using NRSER::Types
8
3
 
@@ -1,8 +1,3 @@
1
- require 'spec_helper'
2
-
3
- require 'nrser/refinements'
4
- using NRSER
5
-
6
1
  require 'nrser/refinements/types'
7
2
  using NRSER::Types
8
3
 
@@ -1,8 +1,3 @@
1
- require 'spec_helper'
2
-
3
- require 'nrser/refinements'
4
- using NRSER
5
-
6
1
  require 'nrser/refinements/types'
7
2
  using NRSER::Types
8
3
 
@@ -1,8 +1,3 @@
1
- require 'spec_helper'
2
-
3
- require 'nrser/refinements'
4
- using NRSER
5
-
6
1
  require 'nrser/refinements/types'
7
2
  using NRSER::Types
8
3
 
@@ -203,4 +198,4 @@ describe NRSER::Types do
203
198
  end
204
199
  end # #from_repr
205
200
 
206
- end # QB::Types
201
+ end # QB::Types
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nrser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - nrser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-25 00:00:00.000000000 Z
11
+ date: 2018-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hamster
@@ -331,7 +331,7 @@ files:
331
331
  - lib/nrser/log/formatters/mixin.rb
332
332
  - lib/nrser/log/logger.rb
333
333
  - lib/nrser/log/mixin.rb
334
- - lib/nrser/log/notify.rb
334
+ - lib/nrser/log/plugin.rb
335
335
  - lib/nrser/mean_streak.rb
336
336
  - lib/nrser/mean_streak/document.rb
337
337
  - lib/nrser/message.rb
@@ -1,94 +0,0 @@
1
- # encoding: UTF-8
2
- # frozen_string_literal: true
3
-
4
- # Requirements
5
- # =======================================================================
6
-
7
- # Stdlib
8
- # -----------------------------------------------------------------------
9
-
10
- # Deps
11
- # -----------------------------------------------------------------------
12
-
13
- # Project / Package
14
- # -----------------------------------------------------------------------
15
-
16
- # Need {NRSER::LazyAttr} decorator.
17
- require 'nrser/meta/lazy_attr'
18
-
19
-
20
- # Namespace
21
- # =======================================================================
22
-
23
- module NRSER
24
- module Log
25
-
26
-
27
- # Definitions
28
- # =======================================================================
29
-
30
- # Abstraction to attempt to notify interactive users.
31
- #
32
- module Notify
33
-
34
- +NRSER::LazyAttr
35
- # Is the `terminal-notifier` gem available?
36
- #
37
- # [terminal-notifier][] is not an NRSER dependency since it does not make
38
- # sense for many systems and situations. It must be installed separately.
39
- #
40
- # [terminal-notifier]: https://rubygems.org/gems/terminal-notifier
41
- #
42
- # Tests by trying to `require` it.
43
- #
44
- # @return [Boolean]
45
- #
46
- def self.terminal_notifier?
47
- begin
48
- require 'terminal-notifier'
49
- rescue LoadError => error
50
- false
51
- else
52
- true
53
- end
54
- end # .terminal_notifier?
55
-
56
-
57
- +NRSER::LazyAttr
58
- # Can we send notification to the user?
59
- #
60
- # Right now, only {.terminal_notifier?} is tested, but we can add more
61
- # options in the future.
62
- #
63
- # @return [Boolean]
64
- #
65
- def self.available?
66
- terminal_notifier?
67
- end # .available?
68
-
69
-
70
- # Send a notification to the use *if* notifications are {.available?}.
71
- #
72
- #
73
- def self.notify *args, &block
74
- return false unless available?
75
-
76
- notify! *args, &block
77
- end
78
-
79
-
80
- def self.notify! *args, &block
81
- require 'terminal-notifier'
82
-
83
- TerminalNotifier.notify *args, &block
84
- end
85
-
86
-
87
- end # module Notify
88
-
89
-
90
- # /Namespace
91
- # =======================================================================
92
-
93
- end # module Log
94
- end # module NRSER