cond 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +334 -0
- data/Rakefile +195 -0
- data/cond.gemspec +37 -0
- data/examples/bad_example.rb +51 -0
- data/examples/calc_example.rb +84 -0
- data/examples/readme_example.rb +27 -0
- data/examples/restarts_example.rb +26 -0
- data/examples/seibel_example.rb +18 -0
- data/install.rb +3 -0
- data/lib/cond.rb +456 -0
- data/lib/cond/cond_private/defaults.rb +78 -0
- data/lib/cond/cond_private/symbol_generator.rb +45 -0
- data/lib/cond/cond_private/thread_local.rb +77 -0
- data/readmes/restarts.rb +84 -0
- data/readmes/seibel_pcl.rb +129 -0
- data/spec/basic_spec.rb +66 -0
- data/spec/common.rb +49 -0
- data/spec/error_spec.rb +55 -0
- data/spec/leave_again_spec.rb +88 -0
- data/spec/matching_spec.rb +86 -0
- data/spec/raise_spec.rb +69 -0
- data/spec/reraise_spec.rb +101 -0
- data/spec/specs_spec.rb +16 -0
- data/spec/symbols_spec.rb +33 -0
- data/spec/thread_local_spec.rb +29 -0
- data/spec/wrapping_spec.rb +93 -0
- data/support/quix/ruby.rb +51 -0
- data/support/quix/simple_installer.rb +88 -0
- metadata +93 -0
data/spec/specs_spec.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
here = File.dirname(__FILE__)
|
2
|
+
require here + "/common"
|
3
|
+
|
4
|
+
require 'quix/ruby'
|
5
|
+
|
6
|
+
describe "specs" do
|
7
|
+
it "should run individually" do
|
8
|
+
(Dir["#{here}/*_spec.rb"] + Dir["#{here}/../examples/*_example.rb"]).each {
|
9
|
+
|spec|
|
10
|
+
unless File.basename(spec) == File.basename(__FILE__)
|
11
|
+
`"#{Quix::Ruby::EXECUTABLE}" "#{spec}"`
|
12
|
+
$?.exitstatus.should == 0
|
13
|
+
end
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/common"
|
2
|
+
|
3
|
+
#
|
4
|
+
# Try to demonstrate symbol recycling by calling GC.start on each pass
|
5
|
+
# through a symbol-generating loop.
|
6
|
+
#
|
7
|
+
# I have not yet seen jruby call the finalizers required for symbol
|
8
|
+
# recycling.
|
9
|
+
#
|
10
|
+
|
11
|
+
def symbols_spec(&block)
|
12
|
+
if defined?(RUBY_ENGINE) and RUBY_ENGINE == "jruby"
|
13
|
+
xit "jruby failing #{File.basename(__FILE__)}", &block
|
14
|
+
else
|
15
|
+
it "should be recycled", &block
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "generated symbols" do
|
20
|
+
symbols_spec do
|
21
|
+
histogram = Hash.new { |hash, key| hash[key] = 0 }
|
22
|
+
|
23
|
+
300.times { |n|
|
24
|
+
obj = Cond::CondPrivate::CodeSection.new(:foo)
|
25
|
+
leave, again = obj.instance_eval { [@leave, @again] }
|
26
|
+
histogram[leave] += 1
|
27
|
+
histogram[again] += 1
|
28
|
+
GC.start
|
29
|
+
}
|
30
|
+
|
31
|
+
histogram.values.any? { |t| t > 1 }.should == true
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/common"
|
2
|
+
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
describe "ThreadLocal" do
|
6
|
+
it "should keep independent values in separate threads" do
|
7
|
+
a = Cond::CondPrivate::ThreadLocal.new { OpenStruct.new }
|
8
|
+
a.value.x = 33
|
9
|
+
other_value = nil
|
10
|
+
Thread.new {
|
11
|
+
a.value.x = 44
|
12
|
+
other_value = a.value.x
|
13
|
+
}.join
|
14
|
+
|
15
|
+
a.value.x.should == 33
|
16
|
+
other_value.should == 44
|
17
|
+
a.clear { 99 }
|
18
|
+
a.value.should == 99
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should work with included accessor_module" do
|
22
|
+
a = Class.new {
|
23
|
+
include Cond::CondPrivate::ThreadLocal.accessor_module(:x) { 33 }
|
24
|
+
}.new
|
25
|
+
a.x.should == 33
|
26
|
+
a.x = 44
|
27
|
+
a.x.should == 44
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/common"
|
2
|
+
|
3
|
+
include Cond
|
4
|
+
|
5
|
+
describe "singleton method defined in C" do
|
6
|
+
before :all do
|
7
|
+
@memo = []
|
8
|
+
@define_handler = lambda {
|
9
|
+
handle ArgumentError do
|
10
|
+
@memo.push :handled
|
11
|
+
end
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "unwrapped" do
|
16
|
+
it "should unwind" do
|
17
|
+
lambda {
|
18
|
+
handling do
|
19
|
+
@define_handler.call
|
20
|
+
IO.read
|
21
|
+
end
|
22
|
+
}.should raise_error(ArgumentError)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should not call handler" do
|
26
|
+
@memo.should == []
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "wrapped" do
|
31
|
+
before :all do
|
32
|
+
Cond.wrap_singleton_method(IO, :read)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should not unwind" do
|
36
|
+
lambda {
|
37
|
+
handling do
|
38
|
+
@define_handler.call
|
39
|
+
IO.read
|
40
|
+
end
|
41
|
+
}.should_not raise_error(ArgumentError)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should call handler" do
|
45
|
+
@memo.should == [:handled]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "instance method defined in C" do
|
51
|
+
before :all do
|
52
|
+
@memo = []
|
53
|
+
@define_handler = lambda {
|
54
|
+
handle ZeroDivisionError do |exception|
|
55
|
+
@memo.push :handled
|
56
|
+
end
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "unwrapped" do
|
61
|
+
it "should unwind" do
|
62
|
+
lambda {
|
63
|
+
handling do
|
64
|
+
@define_handler.call
|
65
|
+
3/0
|
66
|
+
end
|
67
|
+
}.should raise_error(ZeroDivisionError)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should not call handler" do
|
71
|
+
@memo.should == []
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "wrapped" do
|
76
|
+
before :all do
|
77
|
+
Cond.wrap_instance_method(Fixnum, :/)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should not unwind" do
|
81
|
+
lambda {
|
82
|
+
handling do
|
83
|
+
@define_handler.call
|
84
|
+
3/0
|
85
|
+
end
|
86
|
+
}.should_not raise_error(ZeroDivisionError )
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should call handler" do
|
90
|
+
@memo.should == [:handled]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
require 'rbconfig'
|
3
|
+
|
4
|
+
module Quix
|
5
|
+
module Ruby
|
6
|
+
EXECUTABLE = lambda {
|
7
|
+
name = File.join(
|
8
|
+
Config::CONFIG["bindir"],
|
9
|
+
Config::CONFIG["RUBY_INSTALL_NAME"]
|
10
|
+
)
|
11
|
+
|
12
|
+
if Config::CONFIG["host"] =~ %r!(mswin|cygwin|mingw)! and
|
13
|
+
File.basename(name) !~ %r!\.(exe|com|bat|cmd)\Z!i
|
14
|
+
name + ".exe"
|
15
|
+
else
|
16
|
+
name
|
17
|
+
end
|
18
|
+
}.call
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def run(*args)
|
22
|
+
system(EXECUTABLE, *args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def run_or_raise(*args)
|
26
|
+
cmd = [EXECUTABLE, *args]
|
27
|
+
unless system(*cmd)
|
28
|
+
msg = (
|
29
|
+
"failed to launch ruby: " +
|
30
|
+
"system(*#{cmd.inspect}) failed with status #{$?.exitstatus}"
|
31
|
+
)
|
32
|
+
raise msg
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def with_warnings(value = true)
|
37
|
+
previous = $VERBOSE
|
38
|
+
$VERBOSE = value
|
39
|
+
begin
|
40
|
+
yield
|
41
|
+
ensure
|
42
|
+
$VERBOSE = previous
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def no_warnings(&block)
|
47
|
+
with_warnings(false, &block)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
|
2
|
+
require 'rbconfig'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'find'
|
5
|
+
|
6
|
+
module Quix
|
7
|
+
class SimpleInstaller
|
8
|
+
def initialize
|
9
|
+
dest_root = Config::CONFIG["sitelibdir"]
|
10
|
+
sources = []
|
11
|
+
Find.find("./lib") { |source|
|
12
|
+
if install_file?(source)
|
13
|
+
sources << source
|
14
|
+
end
|
15
|
+
}
|
16
|
+
@spec = sources.inject(Array.new) { |acc, source|
|
17
|
+
if source == "./lib"
|
18
|
+
acc
|
19
|
+
else
|
20
|
+
dest = File.join(dest_root, source.sub(%r!\A\./lib!, ""))
|
21
|
+
|
22
|
+
install = lambda {
|
23
|
+
if File.directory?(source)
|
24
|
+
unless File.directory?(dest)
|
25
|
+
puts "mkdir #{dest}"
|
26
|
+
FileUtils.mkdir(dest)
|
27
|
+
end
|
28
|
+
else
|
29
|
+
puts "install #{source} --> #{dest}"
|
30
|
+
FileUtils.install(source, dest)
|
31
|
+
end
|
32
|
+
}
|
33
|
+
|
34
|
+
uninstall = lambda {
|
35
|
+
if File.directory?(source)
|
36
|
+
if File.directory?(dest)
|
37
|
+
puts "rmdir #{dest}"
|
38
|
+
FileUtils.rmdir(dest)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
if File.file?(dest)
|
42
|
+
puts "rm #{dest}"
|
43
|
+
FileUtils.rm(dest)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
}
|
47
|
+
|
48
|
+
acc << {
|
49
|
+
:source => source,
|
50
|
+
:dest => dest,
|
51
|
+
:install => install,
|
52
|
+
:uninstall => uninstall,
|
53
|
+
}
|
54
|
+
end
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def install_file?(source)
|
59
|
+
!File.symlink?(source) and
|
60
|
+
(File.directory?(source) or
|
61
|
+
(File.file?(source) and File.extname(source) == ".rb"))
|
62
|
+
end
|
63
|
+
|
64
|
+
attr_accessor :spec
|
65
|
+
|
66
|
+
def install
|
67
|
+
@spec.each { |entry|
|
68
|
+
entry[:install].call
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def uninstall
|
73
|
+
@spec.reverse.each { |entry|
|
74
|
+
entry[:uninstall].call
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
def run(args = ARGV)
|
79
|
+
if args.empty? or (args.size == 1 and args.first == "install")
|
80
|
+
install
|
81
|
+
elsif args.size == 1 and args.first == "--uninstall"
|
82
|
+
uninstall
|
83
|
+
else
|
84
|
+
raise "unrecognized arguments: #{args.inspect}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cond
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James M. Lawrence
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-03-22 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: +Cond+ allows errors to be handled at the place where they occur. You decide whether or not the stack should be unwound, depending on the circumstance and the error.
|
17
|
+
email: quixoticsycophant@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
files:
|
25
|
+
- README
|
26
|
+
- cond.gemspec
|
27
|
+
- ./examples/bad_example.rb
|
28
|
+
- ./examples/calc_example.rb
|
29
|
+
- ./examples/readme_example.rb
|
30
|
+
- ./examples/restarts_example.rb
|
31
|
+
- ./examples/seibel_example.rb
|
32
|
+
- ./install.rb
|
33
|
+
- ./lib/cond/cond_private/defaults.rb
|
34
|
+
- ./lib/cond/cond_private/symbol_generator.rb
|
35
|
+
- ./lib/cond/cond_private/thread_local.rb
|
36
|
+
- ./lib/cond.rb
|
37
|
+
- ./readmes/restarts.rb
|
38
|
+
- ./readmes/seibel_pcl.rb
|
39
|
+
- ./spec/basic_spec.rb
|
40
|
+
- ./spec/common.rb
|
41
|
+
- ./spec/error_spec.rb
|
42
|
+
- ./spec/leave_again_spec.rb
|
43
|
+
- ./spec/matching_spec.rb
|
44
|
+
- ./spec/raise_spec.rb
|
45
|
+
- ./spec/reraise_spec.rb
|
46
|
+
- ./spec/specs_spec.rb
|
47
|
+
- ./spec/symbols_spec.rb
|
48
|
+
- ./spec/thread_local_spec.rb
|
49
|
+
- ./spec/wrapping_spec.rb
|
50
|
+
- ./support/quix/ruby.rb
|
51
|
+
- ./support/quix/simple_installer.rb
|
52
|
+
- ./Rakefile
|
53
|
+
has_rdoc: true
|
54
|
+
homepage: cond.rubyforge.org
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options:
|
57
|
+
- --main
|
58
|
+
- README
|
59
|
+
- --title
|
60
|
+
- "cond: Resolve errors without unwinding the stack."
|
61
|
+
- --exclude
|
62
|
+
- spec
|
63
|
+
- --exclude
|
64
|
+
- examples
|
65
|
+
- --exclude
|
66
|
+
- readmes
|
67
|
+
- --exclude
|
68
|
+
- support
|
69
|
+
- --exclude
|
70
|
+
- lib/cond/cond_private
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
version:
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: "0"
|
84
|
+
version:
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project: cond
|
88
|
+
rubygems_version: 1.3.1
|
89
|
+
signing_key:
|
90
|
+
specification_version: 2
|
91
|
+
summary: Resolve errors without unwinding the stack.
|
92
|
+
test_files: []
|
93
|
+
|