rogerdpack-remembered_evals 0.0.1 → 0.0.3
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.
- data/README +19 -0
- data/lib/remembered_evals.rb +74 -17
- metadata +7 -5
data/README
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
remembered_evals:
|
2
|
+
|
3
|
+
A library to make debugging eval'ed code possible. It monkey patches Kernel.eval, module_eval, and class_eval to save eval'ed code to a file at ._remembered_evals/hash_of_that_file
|
4
|
+
|
5
|
+
Thus you can debug [ex: using ruby-debug] THROUGH eval'ed code, now, as well as see appropriate (better) eval'ed code lines in exception backtraces.
|
6
|
+
|
7
|
+
Since it saves files by hash, and doesn't rewrite them once saved, you could also edit eval'ed blocks and it will use the edited versions--i.e. it allows you to override certain strings passed to eval [it uses yours instead of the original]-- quite useful for debugging purposes if you use eval at all.
|
8
|
+
|
9
|
+
Note that if all you want to do is save the code away [not debug through] then you can
|
10
|
+
set
|
11
|
+
SCRIPT_LINES__ = {}
|
12
|
+
somewhere in your script.
|
13
|
+
|
14
|
+
Note also that it breaks eval'ed code that assumes the default binding, i.e.
|
15
|
+
a = 3
|
16
|
+
eval("a = 4") # breaks
|
17
|
+
eval("a = 4", binding) # works though
|
18
|
+
|
19
|
+
The price we pay for debugging convenience. You may want to therefore do all you gem requires before loading it.
|
data/lib/remembered_evals.rb
CHANGED
@@ -1,37 +1,94 @@
|
|
1
1
|
require 'digest/md5'
|
2
2
|
require 'rubygems'
|
3
3
|
require 'facets/file/write'
|
4
|
+
require 'facets/file/read' # File.sanitize
|
4
5
|
|
5
|
-
module Kernel
|
6
|
-
alias :original_eval :eval
|
7
6
|
|
8
7
|
=begin rdoc
|
9
|
-
|
10
8
|
doctest: eval saves away files into some path, then eval's them from there
|
11
9
|
>> eval "$a = 3"
|
12
|
-
>> File.directory? '.
|
10
|
+
>> File.directory? '._remembered_evals'
|
13
11
|
=> true
|
14
12
|
>> $a
|
15
13
|
=> 3
|
16
14
|
|
17
|
-
TODO work with class_eval, too
|
18
15
|
|
19
|
-
|
20
|
-
|
21
|
-
>>
|
22
|
-
|
23
|
-
>> true
|
16
|
+
Using it causes the backtraces to behave slightly differently [I'd call it better]
|
17
|
+
>> eval "begin; raise; rescue Exception => e; $exception = e; end"
|
18
|
+
>> $exception.backtrace[0]
|
19
|
+
=> "._remembered_evals/beginraiserescueExceptiona48fc331d57ebd559347525d306d6a67:1:in `eval'"
|
24
20
|
|
25
21
|
=end
|
26
|
-
|
27
|
-
def
|
28
|
-
path = '.
|
22
|
+
class RememberedEval
|
23
|
+
def self.cache_code code_string
|
24
|
+
path = '._remembered_evals'
|
29
25
|
Dir.mkdir path unless File.directory? path
|
30
|
-
|
31
|
-
fullpath = path + '/' + Digest::MD5.hexdigest(
|
32
|
-
|
33
|
-
|
26
|
+
# create something like /code0xdeadbeef for filename
|
27
|
+
fullpath = path + '/' + File.sanitize(code_string[0..31]).gsub('_', '') + Digest::MD5.hexdigest(code_string)[0..63] # don't need too long here
|
28
|
+
if File.exist? fullpath
|
29
|
+
code_string = File.read(fullpath)
|
30
|
+
else
|
31
|
+
File.write(fullpath, code_string) # write it out [prefer old data there, so people can edit them by hand if they are experimenting with eval'ed code]
|
32
|
+
end
|
33
|
+
[code_string, fullpath]
|
34
34
|
end
|
35
35
|
|
36
36
|
end
|
37
37
|
|
38
|
+
class Module
|
39
|
+
alias :original_class_eval :module_eval
|
40
|
+
|
41
|
+
def module_eval *args
|
42
|
+
if block_given? # this one is already sourced
|
43
|
+
original_class_eval { yield }
|
44
|
+
else
|
45
|
+
code, path = RememberedEval.cache_code args[0]
|
46
|
+
original_class_eval code, path, 1 # no binding here
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class Class
|
52
|
+
alias :original_class_eval :class_eval
|
53
|
+
|
54
|
+
def class_eval *args
|
55
|
+
if block_given? # this one is already sourced
|
56
|
+
original_class_eval { yield }
|
57
|
+
else
|
58
|
+
code, path = RememberedEval.cache_code args[0]
|
59
|
+
original_class_eval code, path, 1 # no binding here
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
class Object
|
66
|
+
alias :original_eval :eval
|
67
|
+
def eval *args
|
68
|
+
code, path = RememberedEval.cache_code args[0]
|
69
|
+
original_eval code, args[1], path, 1 # args[1] is binding, ignore args[2], 3 [file, line no]
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
=begin rdoc
|
75
|
+
doctest: work with mod, too
|
76
|
+
>> class A; end
|
77
|
+
>> A.class_eval "def go3; 3; end"
|
78
|
+
>> A.new.go3
|
79
|
+
=> 3
|
80
|
+
|
81
|
+
doctest: it reverts back to normal [non-cached] behavior unless you pass it a binding [?]
|
82
|
+
>> a = 3
|
83
|
+
>> eval "a = 4"
|
84
|
+
>> a
|
85
|
+
=> 4
|
86
|
+
|
87
|
+
doctest: works with modules, too
|
88
|
+
>> module M; end
|
89
|
+
>> M.module_eval "def go; 3; end"
|
90
|
+
>> M.instance_methods
|
91
|
+
=> ["go"]
|
92
|
+
|
93
|
+
=end
|
94
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rogerdpack-remembered_evals
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roger Pack
|
@@ -39,15 +39,17 @@ executables: []
|
|
39
39
|
|
40
40
|
extensions: []
|
41
41
|
|
42
|
-
extra_rdoc_files:
|
43
|
-
|
42
|
+
extra_rdoc_files:
|
43
|
+
- README
|
44
44
|
files:
|
45
45
|
- lib/remembered_evals.rb
|
46
|
+
- README
|
46
47
|
has_rdoc: false
|
47
48
|
homepage: http://github.com/rogerdpack/ruby_remembered_eval/tree/master
|
48
49
|
post_install_message:
|
49
|
-
rdoc_options:
|
50
|
-
|
50
|
+
rdoc_options:
|
51
|
+
- --main
|
52
|
+
- README
|
51
53
|
require_paths:
|
52
54
|
- lib
|
53
55
|
required_ruby_version: !ruby/object:Gem::Requirement
|