console 1.11.1 → 1.12.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 149a9d0738e731ea3ef3159cd25a449f663070406dfa232538a5996fb93c9ce9
4
- data.tar.gz: 212772395d4aef7dc7a510d6630e11dfabeb4c8cf2c70f5d272c279a3d2a32ef
3
+ metadata.gz: '019b21198110cd3da94ef40ce3d666ea19be493e1ef2fa85e818bdd03d67e864'
4
+ data.tar.gz: 33994cbf5c6349aed18c79f3b20527785de1dd1c2307c49b864382750c2d807d
5
5
  SHA512:
6
- metadata.gz: d02021cfb6dbf99651d5f1b8653394dd59f2c830b0a62b8c394b70b275030cd2c066a786a9cb1281df55029f9a69455c00a73a1763785cba3a5ccf8769766654
7
- data.tar.gz: be05f291ccae55c3a6cce6ed2e5e79fa968682d856bcc502693408c69cc85b563017e8505a0459f6cb0d628bbdc57b58efd28146b460e09b45695652e6263145
6
+ metadata.gz: dc7b76666ff0f3dda0cfaf3d966f8cd00bae86d0930f34452e6dcd20dc42fac72d2ba9a7533f6dc9bf7790cdb4e1c98c97830434bc36a463ae156104c6caa657
7
+ data.tar.gz: 9bc0323787283b1fd20357914b1ff12eb1cd19bc20f68c7132bacf7533817829f514d5b408b5421366bf07a38265417ad3b3d93cc1984844affe5d91b0f0889c
@@ -33,6 +33,10 @@ module Console
33
33
  @buffer.last
34
34
  end
35
35
 
36
+ def include?(pattern)
37
+ JSON.dump(@buffer).include?(pattern)
38
+ end
39
+
36
40
  def clear
37
41
  @buffer.clear
38
42
  end
@@ -26,11 +26,12 @@ module Console
26
26
  class Filter
27
27
  def self.[] **levels
28
28
  klass = Class.new(self)
29
+ min_level, max_level = levels.values.minmax
29
30
 
30
31
  klass.instance_exec do
31
32
  const_set(:LEVELS, levels)
32
- const_set(:MINIMUM_LEVEL, levels.values.min)
33
- const_set(:MAXIMUM_LEVEL, levels.values.max)
33
+ const_set(:MINIMUM_LEVEL, min_level)
34
+ const_set(:MAXIMUM_LEVEL, max_level)
34
35
 
35
36
  levels.each do |name, level|
36
37
  const_set(name.to_s.upcase, level)
@@ -102,7 +103,7 @@ module Console
102
103
  end
103
104
 
104
105
  def all!
105
- @level = -1
106
+ @level = self.class::MINIMUM_LEVEL - 1
106
107
  end
107
108
 
108
109
  # You can enable and disable logging for classes. This function checks if logging for a given subject is enabled.
@@ -18,12 +18,14 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
+ require_relative 'output'
21
22
  require_relative 'filter'
22
23
  require_relative 'measure'
23
24
  require_relative 'progress'
24
25
 
25
26
  require_relative 'resolver'
26
27
  require_relative 'terminal/logger'
28
+ require_relative 'serialized/logger'
27
29
 
28
30
  require 'fiber/local'
29
31
 
@@ -35,7 +37,7 @@ module Console
35
37
  # You can also specify CONSOLE_LEVEL=debug or CONSOLE_LEVEL=info in environment.
36
38
  # https://mislav.net/2011/06/ruby-verbose-mode/ has more details about how it all fits together.
37
39
  def self.default_log_level(env = ENV)
38
- if level = (env['CONSOLE_LEVEL'] || env['CONSOLE_LOG_LEVEL'])
40
+ if level = env['CONSOLE_LEVEL']
39
41
  LEVELS[level.to_sym] || level.to_i
40
42
  elsif $DEBUG
41
43
  DEBUG
@@ -51,17 +53,25 @@ module Console
51
53
  !$VERBOSE.nil? || env['CONSOLE_VERBOSE']
52
54
  end
53
55
 
54
- def self.default_logger(output, verbose: self.verbose?, level: self.default_log_level)
55
- terminal = Terminal::Logger.new(output, verbose: verbose)
56
+ def self.default_logger(output = $stderr, env = ENV, **options)
57
+ if options[:verbose].nil?
58
+ options[:verbose] = self.verbose?(env)
59
+ end
60
+
61
+ if options[:level].nil?
62
+ options[:level] = self.default_log_level(env)
63
+ end
64
+
65
+ output = Output.new(output, env, **options)
66
+ logger = self.new(output, **options)
56
67
 
57
- logger = self.new(terminal, verbose: verbose, level: level)
58
68
  Resolver.default_resolver(logger)
59
69
 
60
70
  return logger
61
71
  end
62
72
 
63
73
  def self.local
64
- self.default_logger($stderr)
74
+ self.default_logger
65
75
  end
66
76
 
67
77
  DEFAULT_LEVEL = 1
@@ -0,0 +1,40 @@
1
+ # Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
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.
20
+
21
+ require_relative 'output/default'
22
+ require_relative 'output/json'
23
+ require_relative 'output/text'
24
+ require_relative 'output/xterm'
25
+
26
+ module Console
27
+ module Output
28
+ def self.new(output = nil, env = ENV, **options)
29
+ if names = env['CONSOLE_OUTPUT']
30
+ names = names.split(',').map(&:to_sym).reverse
31
+
32
+ names.inject(output) do |output, name|
33
+ Output.const_get(name).new(output, **options)
34
+ end
35
+ else
36
+ return Output::Default.new(output, **options)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,38 @@
1
+ # Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
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.
20
+
21
+ require_relative 'xterm'
22
+ require_relative 'json'
23
+
24
+ module Console
25
+ module Output
26
+ module Default
27
+ def self.new(output, **options)
28
+ output ||= $stderr
29
+
30
+ if output.tty?
31
+ XTerm.new(output, **options)
32
+ else
33
+ JSON.new(output, **options)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,31 @@
1
+ # Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
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.
20
+
21
+ require_relative '../serialized/logger'
22
+
23
+ module Console
24
+ module Output
25
+ module JSON
26
+ def self.new(output, **options)
27
+ Serialized::Logger.new(output, format: ::JSON, **options)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,118 @@
1
+ # Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
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.
20
+
21
+ require_relative '../serialized/logger'
22
+
23
+ module Console
24
+ module Output
25
+ class Sensitive
26
+ def initialize(output, **options)
27
+ @output = output
28
+ end
29
+
30
+ REDACT = /
31
+ phone
32
+ | email
33
+ | full_?name
34
+ | first_?name
35
+ | last_?name
36
+
37
+ | device_name
38
+ | user_agent
39
+
40
+ | zip
41
+ | address
42
+ | location
43
+ | latitude
44
+ | longitude
45
+
46
+ | ip
47
+ | gps
48
+
49
+ | sex
50
+ | gender
51
+
52
+ | token
53
+ | password
54
+ /xi
55
+
56
+ def redact?(text)
57
+ text.match?(REDACT)
58
+ end
59
+
60
+ def redact_hash(arguments, filter)
61
+ arguments.transform_values do |value|
62
+ redact(value, filter)
63
+ end
64
+ end
65
+
66
+ def redact_array(array, filter)
67
+ array.map do |value|
68
+ redact(value, filter)
69
+ end
70
+ end
71
+
72
+ def redact(argument, filter)
73
+ case argument
74
+ when String
75
+ if filter
76
+ filter.call(argument)
77
+ elsif redact?(argument)
78
+ "[REDACTED]"
79
+ else
80
+ argument
81
+ end
82
+ when Array
83
+ redact_array(argument, filter)
84
+ when Hash
85
+ redact_hash(argument, filter)
86
+ else
87
+ redact(argument.to_s, filter)
88
+ end
89
+ end
90
+
91
+ class Filter
92
+ def initialize(substitutions)
93
+ @substitutions = substitutions
94
+ @pattern = Regexp.union(substitutions.keys)
95
+ end
96
+
97
+ def call(text)
98
+ text.gsub(@pattern, @substitutions)
99
+ end
100
+ end
101
+
102
+ def call(subject = nil, *arguments, sensitive: true, **options, &block)
103
+ if sensitive
104
+ if sensitive.respond_to?(:call)
105
+ filter = sensitive
106
+ elsif sensitive.is_a?(Hash)
107
+ filter = Filter.new(sensitive)
108
+ end
109
+
110
+ subject = redact(subject, filter)
111
+ arguments = redact_array(arguments, filter)
112
+ end
113
+
114
+ @output.call(subject, *arguments, **options)
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,31 @@
1
+ # Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
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.
20
+
21
+ require_relative '../terminal/logger'
22
+
23
+ module Console
24
+ module Output
25
+ module Text
26
+ def self.new(output, **options)
27
+ Terminal::Logger.new(output, format: Terminal::Text, **options)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ # Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
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.
20
+
21
+ require_relative '../terminal/logger'
22
+
23
+ module Console
24
+ module Output
25
+ module XTerm
26
+ def self.new(output, **options)
27
+ Terminal::Logger.new(output, format: Terminal::XTerm, **options)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -26,6 +26,8 @@ module Console
26
26
  #
27
27
  # e.g. `CONSOLE_WARN=Acorn,Banana CONSOLE_DEBUG=Cat` will set the log level for the classes Acorn and Banana to `warn` and Cat to `debug`. This overrides the default log level.
28
28
  #
29
+ # You can enable all log levels for a given class by using `CONSOLE_ON=MyClass`. Similarly you can disable all logging using `CONSOLE_OFF=MyClass`.
30
+ #
29
31
  # @parameter logger [Logger] A logger instance to set the logging levels on.
30
32
  # @parameter env [Hash] The environment to read levels from.
31
33
  #
@@ -33,23 +35,42 @@ module Console
33
35
  # @returns [Resolver] If there were custom logging levels, then the created resolver is returned.
34
36
  def self.default_resolver(logger, env = ENV)
35
37
  # Find all CONSOLE_<LEVEL> variables from environment:
36
- levels = Logger::LEVELS
38
+ levels = logger.class::LEVELS
37
39
  .map{|label, level| [level, env["CONSOLE_#{label.upcase}"]&.split(',')]}
38
40
  .to_h
39
41
  .compact
40
42
 
43
+ off_klasses = env['CONSOLE_OFF']&.split(',')
44
+ on_klasses = env['CONSOLE_ON']&.split(',')
45
+
46
+ resolver = nil
47
+
41
48
  # If we have any levels, then create a class resolver, and each time a class is resolved, set the log level for that class to the specified level:
42
- if levels.any?
43
- resolver = Resolver.new
49
+ if on_klasses&.any?
50
+ resolver ||= Resolver.new
44
51
 
45
- levels.each do |level, names|
46
- resolver.bind(names) do |klass|
47
- logger.enable(klass, level)
48
- end
52
+ resolver.bind(on_klasses) do |klass|
53
+ logger.enable(klass, logger.class::MINIMUM_LEVEL - 1)
49
54
  end
55
+ end
56
+
57
+ if off_klasses&.any?
58
+ resolver ||= Resolver.new
50
59
 
51
- return resolver
60
+ resolver.bind(off_klasses) do |klass|
61
+ logger.disable(klass)
62
+ end
52
63
  end
64
+
65
+ levels.each do |level, names|
66
+ resolver ||= Resolver.new
67
+
68
+ resolver.bind(names) do |klass|
69
+ logger.enable(klass, level)
70
+ end
71
+ end
72
+
73
+ return resolver
53
74
  end
54
75
 
55
76
  def initialize
@@ -27,7 +27,7 @@ require 'json'
27
27
  module Console
28
28
  module Serialized
29
29
  class Logger
30
- def initialize(io = $stderr, format: JSON)
30
+ def initialize(io = $stderr, format: JSON, **options)
31
31
  @io = io
32
32
  @start = Time.now
33
33
  @format = format
@@ -55,11 +55,11 @@ module Console
55
55
  end
56
56
 
57
57
  class Logger
58
- def initialize(io = $stderr, verbose: nil, start_at: Terminal.start_at!, **options)
58
+ def initialize(io = $stderr, verbose: nil, start_at: Terminal.start_at!, format: nil, **options)
59
59
  @io = io
60
60
  @start_at = start_at
61
61
 
62
- @terminal = Terminal.for(io)
62
+ @terminal = format.nil? ? Terminal.for(io) : format.new(io)
63
63
 
64
64
  if verbose.nil?
65
65
  @verbose = !@terminal.colors?
@@ -19,5 +19,5 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module Console
22
- VERSION = "1.11.1"
22
+ VERSION = "1.12.0"
23
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: console
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.11.1
4
+ version: 1.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-10 00:00:00.000000000 Z
11
+ date: 2021-04-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fiber-local
@@ -115,6 +115,12 @@ files:
115
115
  - lib/console/filter.rb
116
116
  - lib/console/logger.rb
117
117
  - lib/console/measure.rb
118
+ - lib/console/output.rb
119
+ - lib/console/output/default.rb
120
+ - lib/console/output/json.rb
121
+ - lib/console/output/sensitive.rb
122
+ - lib/console/output/text.rb
123
+ - lib/console/output/xterm.rb
118
124
  - lib/console/progress.rb
119
125
  - lib/console/resolver.rb
120
126
  - lib/console/serialized/logger.rb