monkey 0.0.0 → 0.6.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.
- data/README.rdoc +58 -12
- data/Rakefile +36 -42
- data/VERSION +1 -1
- data/lib/monkey/ext/modexcl/mrimodexcl.rb +82 -0
- data/lib/monkey/ext/modexcl/rbmodexcl.rb +5 -0
- data/lib/monkey/ext/modexcl/rbxmodexcl.rb +48 -0
- data/lib/monkey.rb +135 -0
- metadata +57 -21
- data/.document +0 -5
- data/.gitignore +0 -21
- data/LICENSE +0 -20
- data/test/helper.rb +0 -10
- data/test/test_monkey.rb +0 -7
data/README.rdoc
CHANGED
@@ -1,17 +1,63 @@
|
|
1
|
-
=
|
1
|
+
= Monkey
|
2
2
|
|
3
|
-
|
3
|
+
Monkey is a smart, scoped monkeypatching library. You can define monkeypatches
|
4
|
+
via an intuitive DSL, and apply them only to scoped blocks, assured that your
|
5
|
+
changes won't leak out to objects outside your scope.
|
4
6
|
|
5
|
-
==
|
7
|
+
== Usage
|
8
|
+
|
9
|
+
=== Monkeypatching objects
|
10
|
+
|
11
|
+
# define the "metaclass" monkeypatch on Object
|
12
|
+
Monkey.see(Object) do
|
13
|
+
def metaclass
|
14
|
+
class << self; self; end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# patch Object to include the "metaclass" monkeypatch for the duration of
|
19
|
+
# the block
|
20
|
+
Monkey.patch(Object, :metaclass) do
|
21
|
+
"foo".metaclass # => #<Class:#<String:0x1016d7570>>
|
22
|
+
end
|
23
|
+
|
24
|
+
# the monkeypatch doesn't make it out of the scope
|
25
|
+
"foo".metaclass # => NoMethodError
|
26
|
+
|
27
|
+
# patch Object to include the "metaclass" monkeypatch
|
28
|
+
Monkey.patch(Object, :metaclass)
|
29
|
+
|
30
|
+
# the monkeypatch persists
|
31
|
+
"foo".metaclass # => #<Class:#<String:0x1016d7570>>
|
32
|
+
|
33
|
+
=== Monkeypatching classes
|
6
34
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
35
|
+
# define the "foo" and "bar" monkeypatches on the class-level of Object
|
36
|
+
Monkey.see(Object.metaclass) do
|
37
|
+
def foo
|
38
|
+
Kernel.rand
|
39
|
+
end
|
40
|
+
|
41
|
+
def bar
|
42
|
+
"hello!"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
Monkey.patch(Object.metaclass, :foo, :bar) do
|
47
|
+
Object.foo # => 0.571499912853919
|
48
|
+
Object.bar # => "hello!"
|
49
|
+
end
|
14
50
|
|
15
|
-
|
51
|
+
=== Monkeypatching instances
|
16
52
|
|
17
|
-
|
53
|
+
# define the "metaclass" monkeypatch on Object
|
54
|
+
Monkey.see(Object) do
|
55
|
+
def metaclass
|
56
|
+
class << self; self; end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
a = "foo"
|
61
|
+
|
62
|
+
Monkey.patch(a, :metaclass) { a.metaclass }
|
63
|
+
|
data/Rakefile
CHANGED
@@ -1,52 +1,46 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'rake'
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
gem.summary = %Q{Scopeable monkeypatching support for Ruby}
|
9
|
-
gem.description = %Q{This is just a dummy package to reserve the name until the project is ready to be released}
|
10
|
-
gem.email = "stephen@touset.org"
|
11
|
-
gem.homepage = "http://github.com/stouset/monkey"
|
12
|
-
gem.authors = ["Stephen Touset"]
|
13
|
-
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
-
end
|
15
|
-
Jeweler::GemcutterTasks.new
|
16
|
-
rescue LoadError
|
17
|
-
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
18
|
-
end
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require 'rake/version_task'
|
6
|
+
require 'spec/rake/spectask'
|
19
7
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
8
|
+
spec = Gem::Specification.new do |s|
|
9
|
+
s.name = 'monkey'
|
10
|
+
s.version = Version.current
|
11
|
+
s.summary = 'A smart, scoped monkeypatching library'
|
12
|
+
|
13
|
+
s.author = 'Stephen Touset'
|
14
|
+
s.email = 'stephen@touset.org'
|
15
|
+
|
16
|
+
s.files = Dir['[A-Z]*', 'lib/**/*.rb', 'spec/**/*']
|
17
|
+
|
18
|
+
s.extra_rdoc_files = Dir['*.rdoc']
|
19
|
+
s.rdoc_options = %w{ --main README.rdoc }
|
20
|
+
|
21
|
+
s.add_development_dependency 'version'
|
22
|
+
s.add_development_dependency 'rspec'
|
25
23
|
end
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
Rcov::RcovTask.new do |test|
|
30
|
-
test.libs << 'test'
|
31
|
-
test.pattern = 'test/**/test_*.rb'
|
32
|
-
test.verbose = true
|
33
|
-
end
|
34
|
-
rescue LoadError
|
35
|
-
task :rcov do
|
36
|
-
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
37
|
-
end
|
25
|
+
Rake::GemPackageTask.new(spec) do |gem|
|
26
|
+
gem.need_tar = true
|
38
27
|
end
|
39
28
|
|
40
|
-
|
41
|
-
|
42
|
-
|
29
|
+
Rake::RDocTask.new do |doc|
|
30
|
+
doc.title = "monkey #{Version.current}"
|
31
|
+
doc.rdoc_dir = 'doc'
|
32
|
+
doc.main = 'README.rdoc'
|
33
|
+
doc.rdoc_files.include('*.rdoc')
|
34
|
+
doc.rdoc_files.include('lib/**/*.rb')
|
35
|
+
end
|
43
36
|
|
44
|
-
|
45
|
-
|
46
|
-
|
37
|
+
Spec::Rake::SpecTask.new(:spec) do |task|
|
38
|
+
task.spec_files = FileList['spec/**/*_spec.rb']
|
39
|
+
end
|
47
40
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
41
|
+
Rake::VersionTask.new do |v|
|
42
|
+
v.with_git_tag = true
|
43
|
+
v.with_gemspec = spec
|
52
44
|
end
|
45
|
+
|
46
|
+
task :default => :spec
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'inline'
|
3
|
+
|
4
|
+
class Object
|
5
|
+
inline(:C) do |builder|
|
6
|
+
builder.prefix %{
|
7
|
+
static VALUE
|
8
|
+
rb_obj_dummy()
|
9
|
+
{
|
10
|
+
return Qnil;
|
11
|
+
}
|
12
|
+
}
|
13
|
+
builder.add_to_init %{
|
14
|
+
rb_define_private_method(rb_cModule, "unextended", rb_obj_dummy, 1);
|
15
|
+
}
|
16
|
+
builder.c %{
|
17
|
+
VALUE unextend(VALUE mod)
|
18
|
+
{
|
19
|
+
VALUE p, prev;
|
20
|
+
Check_Type(mod, T_MODULE);
|
21
|
+
if (mod == rb_mKernel)
|
22
|
+
rb_raise(rb_eArgError, "unextending Kernel is prohibited");
|
23
|
+
|
24
|
+
|
25
|
+
p = rb_singleton_class(self);
|
26
|
+
|
27
|
+
while (p) {
|
28
|
+
if (p == mod || RCLASS(p)->m_tbl == RCLASS(mod)->m_tbl) {
|
29
|
+
RCLASS(prev)->super = RCLASS(p)->super;
|
30
|
+
rb_clear_cache();
|
31
|
+
rb_funcall(mod, rb_intern("unextended"), 1, self);
|
32
|
+
return self;
|
33
|
+
}
|
34
|
+
prev = p;
|
35
|
+
p = RCLASS(p)->super;
|
36
|
+
}
|
37
|
+
return self;
|
38
|
+
}
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
class Class
|
45
|
+
|
46
|
+
inline(:C) do |builder|
|
47
|
+
builder.prefix %{
|
48
|
+
static VALUE
|
49
|
+
rb_obj_dummy()
|
50
|
+
{
|
51
|
+
return Qnil;
|
52
|
+
}
|
53
|
+
}
|
54
|
+
builder.add_to_init %{
|
55
|
+
rb_define_private_method(rb_cModule, "unincluded", rb_obj_dummy, 1);
|
56
|
+
}
|
57
|
+
builder.c %{
|
58
|
+
VALUE uninclude(VALUE mod)
|
59
|
+
{
|
60
|
+
VALUE p, prev;
|
61
|
+
Check_Type(mod, T_MODULE);
|
62
|
+
if (mod == rb_mKernel)
|
63
|
+
rb_raise(rb_eArgError, "unincluding Kernel is prohibited");
|
64
|
+
|
65
|
+
p = self;
|
66
|
+
|
67
|
+
while (p) {
|
68
|
+
if (p == mod || RCLASS(p)->m_tbl == RCLASS(mod)->m_tbl) {
|
69
|
+
RCLASS(prev)->super = RCLASS(p)->super;
|
70
|
+
rb_clear_cache();
|
71
|
+
rb_funcall(mod, rb_intern("unincluded"), 1, self);
|
72
|
+
return self;
|
73
|
+
}
|
74
|
+
prev = p;
|
75
|
+
p = RCLASS(p)->super;
|
76
|
+
}
|
77
|
+
return self;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
class Object
|
3
|
+
|
4
|
+
def unextend(mod)
|
5
|
+
raise ArgumentError, "Module is expected" unless mod.is_a?(Module)
|
6
|
+
raise ArgumentError, "unextending Kernel is prohibited" if mod == Kernel
|
7
|
+
prev = p = metaclass
|
8
|
+
while p
|
9
|
+
if (p == mod || (p.respond_to?(:module) && p.module == mod))
|
10
|
+
prev.set_superclass(p.direct_superclass)
|
11
|
+
# remove cache
|
12
|
+
self.methods.each do |name|
|
13
|
+
name = self.metaclass.send(:normalize_name,name)
|
14
|
+
Rubinius::VM.reset_method_cache(name)
|
15
|
+
end
|
16
|
+
#
|
17
|
+
mod.send(:unextended, self) if mod.respond_to?(:unextended)
|
18
|
+
return self
|
19
|
+
end
|
20
|
+
prev = p
|
21
|
+
p = p.direct_superclass
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
def uninclude(mod)
|
27
|
+
raise ArgumentError, "Module is expected" unless mod.is_a?(Module)
|
28
|
+
raise ArgumentError, "unincluding Kernel is prohibited" if mod == Kernel
|
29
|
+
prev = p = self
|
30
|
+
while p
|
31
|
+
if (p == mod || (p.respond_to?(:module) && p.module == mod))
|
32
|
+
prev.superclass=(p.direct_superclass)
|
33
|
+
# remove cache
|
34
|
+
self.methods.each do |name|
|
35
|
+
name = self.metaclass.send(:normalize_name,name)
|
36
|
+
Rubinius::VM.reset_method_cache(name)
|
37
|
+
end
|
38
|
+
#
|
39
|
+
mod.send(:unincluded, self) if mod.respond_to?(:unincluded)
|
40
|
+
return self
|
41
|
+
end
|
42
|
+
prev = p
|
43
|
+
p = p.direct_superclass
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
data/lib/monkey.rb
CHANGED
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'monkey/ext/modexcl/rbmodexcl'
|
3
|
+
|
4
|
+
module Monkey
|
5
|
+
class MonkeyError < StandardError; end
|
6
|
+
class MethodPatchedError < MonkeyError; end
|
7
|
+
class MethodMissingError < MonkeyError; end
|
8
|
+
|
9
|
+
#
|
10
|
+
# Allows you to specify a set of monkey patches that can be applied to a
|
11
|
+
# class or module. Pass a block to the method and define methods inside the
|
12
|
+
# block as normal, and the methods will be available only inside a
|
13
|
+
# Monkey#patch block.
|
14
|
+
#
|
15
|
+
# Raises a Monkey::MethodPatchedError if the +method+ already has a
|
16
|
+
# monkeypatch registered on +klass+.
|
17
|
+
#
|
18
|
+
# Monkey.see(Object) do
|
19
|
+
# def metaclass
|
20
|
+
# (class << self; self; end)
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
def self.see(klass, &block)
|
25
|
+
mod = Module.new(&block)
|
26
|
+
methods = mod.instance_methods(false)
|
27
|
+
|
28
|
+
methods.each do |method|
|
29
|
+
register_patch(klass, method.to_sym, mod)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# Patches +object+ to contain the monkeypatched +methods+. If a block is
|
35
|
+
# passed, the monkeypatches are only active for the duration of the block,
|
36
|
+
# and the return value is the return value of the block.
|
37
|
+
#
|
38
|
+
# Raises a Monkey::MethodMissingError if a named monkeypatch is not defined.
|
39
|
+
#
|
40
|
+
# Monkey.patch(Object, :metaclass) do
|
41
|
+
# "foo".metaclass # => #<Class:#<String:0x10153caf8>>
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# "foo".metaclass # => NoMethodError
|
45
|
+
#
|
46
|
+
def self.patch(object, *methods, &scope)
|
47
|
+
# if the object is a class or metaclass, monkeypatch the class, otherwise
|
48
|
+
# monkeypatch the metaclass of the object
|
49
|
+
if object.kind_of?(Class)
|
50
|
+
_patch(object, object, *methods, &scope)
|
51
|
+
else
|
52
|
+
metaclass = (class << object; self; end)
|
53
|
+
klass = object.class
|
54
|
+
|
55
|
+
_patch(metaclass, klass, *methods, &scope)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
#
|
62
|
+
# Actually applies monkeypatches to +object+. Looks up the +methods+ to be
|
63
|
+
# patched in the scope of of +klass+.
|
64
|
+
#
|
65
|
+
def self._patch(object, klass, *methods, &scope)
|
66
|
+
patches = methods.map do |method|
|
67
|
+
patch = klass.ancestors.map {|a| patch_for(a, method) }.compact.first
|
68
|
+
error_missing(klass, method) if patch.nil?
|
69
|
+
patch
|
70
|
+
end
|
71
|
+
|
72
|
+
scope ? scope_patches(object, *patches, &scope) \
|
73
|
+
: apply_patches(object, *patches)
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# Applies +patches+ to +object+, yields, then removes the patches when the
|
78
|
+
# block returns.
|
79
|
+
#
|
80
|
+
def self.scope_patches(object, *patches)
|
81
|
+
apply_patches(object, *patches)
|
82
|
+
yield
|
83
|
+
ensure
|
84
|
+
remove_patches(object, *patches)
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# Applies the Modules +patches+ to +object+.
|
89
|
+
#
|
90
|
+
def self.apply_patches(object, *patches)
|
91
|
+
patches.each {|patch| object.send(:include, patch) }
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# Removes the Modules +patches+ from +object+.
|
96
|
+
#
|
97
|
+
def self.remove_patches(object, *patches)
|
98
|
+
patches.each {|patch| object.send(:uninclude, patch) }
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Registers a monkeypatch +patch+, which should be a module that defines the
|
103
|
+
# named +method+. The patch is scoped to +klass+ and is named +method+.
|
104
|
+
#
|
105
|
+
def self.register_patch(klass, method, patch)
|
106
|
+
error_patched(klass, method) if patch_for(klass, method)
|
107
|
+
|
108
|
+
self.patches[klass][method] = patch
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
# Looks up the monkeypatch for +method+ in +klass+.
|
113
|
+
#
|
114
|
+
def self.patch_for(klass, method)
|
115
|
+
self.patches[klass][method]
|
116
|
+
end
|
117
|
+
|
118
|
+
#
|
119
|
+
# A nested hash of existing monkeypatch definitions, first by class, then
|
120
|
+
# method name.
|
121
|
+
#
|
122
|
+
def self.patches
|
123
|
+
@patches ||= Hash.new {|h,k| h[k] = Hash.new }
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.error_patched(klass, method)
|
127
|
+
raise MethodPatchedError,
|
128
|
+
"#{klass}##{method} already has a monkeypatch"
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.error_missing(klass, method)
|
132
|
+
raise MethodMissingError,
|
133
|
+
"No monkeypatch #{klass}##{method} has been defined"
|
134
|
+
end
|
135
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: monkey
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 7
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 6
|
9
|
+
- 0
|
10
|
+
version: 0.6.0
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Stephen Touset
|
@@ -9,57 +15,87 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date: 2010-
|
18
|
+
date: 2010-07-12 00:00:00 -04:00
|
13
19
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: version
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
description:
|
17
50
|
email: stephen@touset.org
|
18
51
|
executables: []
|
19
52
|
|
20
53
|
extensions: []
|
21
54
|
|
22
55
|
extra_rdoc_files:
|
23
|
-
- LICENSE
|
24
56
|
- README.rdoc
|
25
57
|
files:
|
26
|
-
- .document
|
27
|
-
- .gitignore
|
28
|
-
- LICENSE
|
29
|
-
- README.rdoc
|
30
58
|
- Rakefile
|
59
|
+
- README.rdoc
|
31
60
|
- VERSION
|
61
|
+
- lib/monkey/ext/modexcl/mrimodexcl.rb
|
62
|
+
- lib/monkey/ext/modexcl/rbmodexcl.rb
|
63
|
+
- lib/monkey/ext/modexcl/rbxmodexcl.rb
|
32
64
|
- lib/monkey.rb
|
33
|
-
- test/helper.rb
|
34
|
-
- test/test_monkey.rb
|
35
65
|
has_rdoc: true
|
36
|
-
homepage:
|
66
|
+
homepage:
|
37
67
|
licenses: []
|
38
68
|
|
39
69
|
post_install_message:
|
40
70
|
rdoc_options:
|
41
|
-
- --
|
71
|
+
- --main
|
72
|
+
- README.rdoc
|
42
73
|
require_paths:
|
43
74
|
- lib
|
44
75
|
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
45
77
|
requirements:
|
46
78
|
- - ">="
|
47
79
|
- !ruby/object:Gem::Version
|
80
|
+
hash: 3
|
81
|
+
segments:
|
82
|
+
- 0
|
48
83
|
version: "0"
|
49
|
-
version:
|
50
84
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
51
86
|
requirements:
|
52
87
|
- - ">="
|
53
88
|
- !ruby/object:Gem::Version
|
89
|
+
hash: 3
|
90
|
+
segments:
|
91
|
+
- 0
|
54
92
|
version: "0"
|
55
|
-
version:
|
56
93
|
requirements: []
|
57
94
|
|
58
95
|
rubyforge_project:
|
59
|
-
rubygems_version: 1.3.
|
96
|
+
rubygems_version: 1.3.7
|
60
97
|
signing_key:
|
61
98
|
specification_version: 3
|
62
|
-
summary:
|
63
|
-
test_files:
|
64
|
-
|
65
|
-
- test/test_monkey.rb
|
99
|
+
summary: A smart, scoped monkeypatching library
|
100
|
+
test_files: []
|
101
|
+
|
data/.document
DELETED
data/.gitignore
DELETED
data/LICENSE
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
Copyright (c) 2009 Stephen Touset
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
a copy of this software and associated documentation files (the
|
5
|
-
"Software"), to deal in the Software without restriction, including
|
6
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
-
permit persons to whom the Software is furnished to do so, subject to
|
9
|
-
the following conditions:
|
10
|
-
|
11
|
-
The above copyright notice and this permission notice shall be
|
12
|
-
included in all copies or substantial portions of the Software.
|
13
|
-
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/test/helper.rb
DELETED