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.
Files changed (3) hide show
  1. data/README +19 -0
  2. data/lib/remembered_evals.rb +74 -17
  3. 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.
@@ -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? '.remembered_evals'
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
- Using it causes the backtraces to behave slightly differently
21
- >> eval "begin; raise; rescue Exception => e; $a = e; end"
22
- >> $a.backtrace[0].include? '.remembered_evals/'
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 eval *args # string, binding, file, line [file and line are hereby ignored since ours supplant it]
28
- path = '.remembered_evals'
22
+ class RememberedEval
23
+ def self.cache_code code_string
24
+ path = '._remembered_evals'
29
25
  Dir.mkdir path unless File.directory? path
30
- digest = Digest::MD5.hexdigest("Hello World\n")
31
- fullpath = path + '/' + Digest::MD5.hexdigest(args[0])
32
- saved = File.write(fullpath, args[0])
33
- original_eval args[0], args[1], fullpath, 1
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.1
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