praise 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/MIT-LICENSE +19 -0
  2. data/lib/praise.rb +103 -0
  3. data/spec/praise.rb +8 -0
  4. metadata +148 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2013 Petr Chalupa <git@pitr.ch>
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.
data/lib/praise.rb ADDED
@@ -0,0 +1,103 @@
1
+ require 'pry'
2
+ require 'pry-stack_explorer'
3
+ require 'yaml'
4
+
5
+ class PraiseImpl
6
+ # @param [Proc] outputter a proc which ouputs/logs messages
7
+ # @param [String] ignored_path path to a yaml file with rules for ignored exceptions
8
+ # @example initialization
9
+ # Praise = PraiseImpl.
10
+ # new(File.join(root, Katello.early_config.praise.ignored_path),
11
+ # -> level, message { Logging.logger['praise'].add Logging.level_num(level), message })
12
+ def initialize(ignored_path, outputter = -> level, message { $stderr.puts message })
13
+ @outputter = outputter
14
+ unless File.exist? ignored_path
15
+ log :info, "creating #{ignored_path} file"
16
+ File.open(ignored_path, 'w') { |f| f.write [].to_yaml }
17
+ end
18
+ @ignored_path = ignored_path
19
+ reload
20
+ install
21
+ end
22
+
23
+ # @return [Array<Hash{:class, :message, :line => Regexp, String}] rules for exception ignoring
24
+ def ignored
25
+ @ignored ||= YAML.load File.read(@ignored_path)
26
+ end
27
+
28
+ # @param [Hash{:class, :message, :line => Regexp, String}] rule for ignoring an exception
29
+ # This will add a rule for exception ignoring. Can be called at runtime, next exception occurrence will be ignored.
30
+ def add_rule(rule)
31
+ ignored = File.open(@ignored_path, 'r') { |f| YAML.load(f.read) }
32
+ File.open(@ignored_path, 'w') { |f| f.write(ignored.push(rule).to_yaml) }
33
+ reload
34
+ end
35
+
36
+ # @return [true, false] should the exception ignored?
37
+ def ignore?(exception_instance, message, risen_at)
38
+ ignored.any? do |hash|
39
+ hash.all? do |type, condition|
40
+ case type
41
+ when :class
42
+ exception_instance.class.to_s == condition
43
+ when :message
44
+ message =~ condition
45
+ when :line
46
+ risen_at =~ condition
47
+ end
48
+ end
49
+ end.tap do |ignore|
50
+ log :debug, "ignored exception: (#{exception_instance.class}) #{message}\n #{risen_at}" if ignore
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ # reload ignored form file
57
+ def reload
58
+ @ignored = nil
59
+ ignored
60
+ end
61
+
62
+ # log `message` on `level`
63
+ def log(level, message)
64
+ @outputter.call(level, message)
65
+ end
66
+
67
+ def install
68
+ log :info, 'installing praise'
69
+ praise = self
70
+ Kernel.module_eval do
71
+ define_method :_original_raise, Kernel.instance_method(:raise)
72
+
73
+ remove_method :raise
74
+ Thread.current[:__pry_in_rescue__] = false
75
+
76
+ define_method :raise do |*args|
77
+ begin
78
+ message = args.find { |o| o.kind_of? String }
79
+ backtrace = args.find { |o| o.kind_of? Array }
80
+ exception_generator = args.find { |o| ![message, backtrace].include? o } || RuntimeError
81
+ #noinspection RubyArgCount
82
+ exception = message ? exception_generator.exception(message) : exception_generator.exception
83
+ message ||= exception.message
84
+ risen_at = caller(1).first
85
+
86
+ unless Thread.current[:__pry_in_rescue__] || praise.ignore?(exception, message, risen_at)
87
+ Thread.current[:__pry_in_rescue__] = true
88
+ binding.pry
89
+ end
90
+
91
+ _original_raise *args
92
+ ensure
93
+ Thread.current[:__pry_in_rescue__] = false
94
+ end
95
+ end
96
+
97
+ # TODO alias fail as well, currently does not work with thin
98
+ #remove_method :fail
99
+ #alias_method :fail, :raise
100
+ end
101
+ self
102
+ end
103
+ end
data/spec/praise.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/setup'
2
+ require 'minitest/autorun'
3
+
4
+ require 'praise'
5
+
6
+ describe 'praise' do
7
+ it { skip 'add some tests' }
8
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: praise
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Petr Chalupa
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: pry
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: pry-stack_explorer
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: minitest
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: pry
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: yard
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: kramdown
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: A small gem for intercepting raise calls to dig up hidden and buried
111
+ exceptions.
112
+ email: git@pitr.ch
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files:
116
+ - MIT-LICENSE
117
+ files:
118
+ - lib/praise.rb
119
+ - MIT-LICENSE
120
+ - spec/praise.rb
121
+ homepage: https://github.com/pitr-ch/praise
122
+ licenses:
123
+ - MIT
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ none: false
136
+ requirements:
137
+ - - ! '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ requirements: []
141
+ rubyforge_project:
142
+ rubygems_version: 1.8.23
143
+ signing_key:
144
+ specification_version: 3
145
+ summary: Intercepts raise calls
146
+ test_files:
147
+ - spec/praise.rb
148
+ has_rdoc: