monkey-lib 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +12 -0
- data/Rakefile +111 -47
- data/lib/monkey.rb +11 -0
- data/lib/monkey/autoloader.rb +2 -0
- data/lib/monkey/backend.rb +97 -32
- data/lib/monkey/backend/active_support.rb +10 -15
- data/lib/monkey/backend/backports.rb +8 -14
- data/lib/monkey/backend/common/parent.rb +4 -6
- data/lib/monkey/backend/common/tap.rb +1 -1
- data/lib/monkey/backend/extlib.rb +10 -18
- data/lib/monkey/backend/facets.rb +11 -18
- data/lib/monkey/ext.rb +20 -12
- data/lib/monkey/ext/module.rb +0 -16
- data/lib/monkey/ext/string.rb +147 -0
- data/spec/monkey/engine_spec.rb +5 -6
- data/spec/monkey/ext/array_spec.rb +18 -0
- data/spec/monkey/ext/module_spec.rb +15 -0
- data/spec/monkey/ext/object_spec.rb +53 -0
- data/spec/monkey/ext/string_spec.rb +331 -0
- data/spec/spec_helper.rb +13 -1
- metadata +10 -23
- data/lib/monkey/string/like_pathname.rb +0 -38
- data/lib/monkey/watcher.rb +0 -139
- data/spec/monkey/hash/sub_hash_spec.rb +0 -15
- data/spec/monkey/object/backports_spec.rb +0 -24
- data/spec/monkey/object/instance_yield_spec.rb +0 -32
- data/spec/monkey/string/like_pathname_spec.rb +0 -272
data/README.rdoc
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
Some description goes here.
|
2
|
+
|
3
|
+
== Running the specs
|
4
|
+
|
5
|
+
Run specs with all backends:
|
6
|
+
rake spec
|
7
|
+
|
8
|
+
Run specs with active_support:
|
9
|
+
rake spec:active_support
|
10
|
+
|
11
|
+
Run specs with backports and using mspec instead of rspec (so it might work on incomplete ruby implementations):
|
12
|
+
SPEC_RUNNER=mspec rake spec:backports
|
data/Rakefile
CHANGED
@@ -1,49 +1,113 @@
|
|
1
|
-
require "spec/rake/spectask"
|
2
1
|
require "rake/clean"
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
s.add_dependency "extlib"
|
22
|
-
end
|
23
|
-
|
24
|
-
Rake::GemPackageTask.new(spec) do |pkg|
|
25
|
-
pkg.gem_spec = spec
|
26
|
-
end
|
27
|
-
|
28
|
-
desc "install the gem locally"
|
29
|
-
task :install => [:package] do
|
30
|
-
sh %{gem install pkg/monkey-lib-#{MONKEY_VERSION}.gem}
|
31
|
-
end
|
32
|
-
|
33
|
-
desc "create a gemspec file"
|
34
|
-
task :make_spec do
|
35
|
-
File.open("monkey-lib.gemspec", "w") do |file|
|
36
|
-
file.puts spec.to_ruby
|
2
|
+
|
3
|
+
task :default => :spec
|
4
|
+
|
5
|
+
backends = Dir.glob('lib/monkey/backend/*.rb').map { |f| File.basename f, ".rb" }
|
6
|
+
modes = [:autodetect, :explicit]
|
7
|
+
|
8
|
+
CLEAN.include "**/*.rbc"
|
9
|
+
CLOBBER.include "monkey-lib*.gem"
|
10
|
+
|
11
|
+
setup_rspec = proc do
|
12
|
+
require "spec/rake/spectask"
|
13
|
+
SPEC_RUNNER = "mspec"
|
14
|
+
def define_spec_task(name, ruby_cmd, pattern)
|
15
|
+
Spec::Rake::SpecTask.new name do |t|
|
16
|
+
t.spec_opts = %w[-c --format progress --loadby mtime --reverse]
|
17
|
+
t.ruby_cmd = ruby_cmd
|
18
|
+
t.pattern = pattern
|
19
|
+
end
|
37
20
|
end
|
38
|
-
end
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
21
|
+
end
|
22
|
+
|
23
|
+
setup_mspec = proc do
|
24
|
+
require "mspec"
|
25
|
+
SPEC_RUNNER = "mspec"
|
26
|
+
def define_spec_task(name, ruby_cmd, pattern)
|
27
|
+
task(name) { sh "#{ruby_cmd} -S mspec-run #{pattern}" }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
case ENV['SPEC_RUNNER']
|
32
|
+
when "rspec" then setup_rspec.call
|
33
|
+
when "mspec" then setup_mspec.call
|
34
|
+
when nil
|
35
|
+
# yes, this code is trying to be smart, but let me have some fun, please?
|
36
|
+
raise @spec_load_error unless [setup_rspec, setup_mspec].any? { |b| b.call || true rescue (@spec_load_error ||= $!) && false }
|
37
|
+
else
|
38
|
+
puts "sorry, currently no #{ENV['SPEC_RUNNER']} support"
|
39
|
+
exit 1
|
40
|
+
end
|
41
|
+
|
42
|
+
def spec_task(name, backend = nil, mode = nil)
|
43
|
+
desc "runs specs #{"with backend #{backend} " if backend}#{"(#{mode} mode)" if mode}"
|
44
|
+
define_spec_task(name, "BACKEND=#{backend.to_s.inspect} BACKEND_SETUP=#{mode.to_s.inspect} #{ENV['RUBY'] || RUBY}", "spec/monkey/**/*_spec.rb")
|
45
|
+
end
|
46
|
+
|
47
|
+
task :environment do
|
48
|
+
$LOAD_PATH.unshift "lib"
|
49
|
+
require "monkey"
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "run all specs"
|
53
|
+
task :spec => "spec:all"
|
54
|
+
namespace :spec do
|
55
|
+
|
56
|
+
desc "runs specs without explicitly setting a backend"
|
57
|
+
spec_task :autodetect
|
58
|
+
|
59
|
+
backends.each do |backend|
|
60
|
+
task :all => backend
|
61
|
+
|
62
|
+
desc "runs specs with backend #{backend}"
|
63
|
+
task backend => "#{backend}:all"
|
64
|
+
|
65
|
+
namespace backend do
|
66
|
+
modes.each do |mode|
|
67
|
+
task :all => mode
|
68
|
+
spec_task mode, backend, mode
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
namespace :backend do
|
76
|
+
|
77
|
+
desc "lists all available backends"
|
78
|
+
task(:list) { puts backends }
|
79
|
+
|
80
|
+
desc "lists expectations a backend has to meet"
|
81
|
+
task :expectations => :environment do
|
82
|
+
Monkey::Ext.expectations.each do |core_class, methods|
|
83
|
+
print "#{core_class}:".ljust(10)
|
84
|
+
puts methods.map { |n| "##{n}" }.join(", ")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
desc "checks whether specs for expectations are present"
|
89
|
+
task :spec_check =>:environment do
|
90
|
+
Monkey::Ext.expectations.each do |core_class, methods|
|
91
|
+
path = "spec/monkey/ext/#{core_class.name.to_const_path}_spec.rb"
|
92
|
+
list = path.file_exists? ? %x[spec -d -fs #{path} -e "Monkey::Ext::#{core_class.name} backend expectations"] : ""
|
93
|
+
methods.each { |m| puts "missing specs for #{core_class.name}##{m}" unless list =~ /- imports #{m} from backend/ }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
############
|
100
|
+
# aliases
|
101
|
+
|
102
|
+
namespace(:b) do
|
103
|
+
task :e => "backend:expectations"
|
104
|
+
task :l => "backend:list"
|
105
|
+
task :s => "backend:spec_check"
|
106
|
+
end
|
107
|
+
|
108
|
+
namespace(:s) do
|
109
|
+
task :as => "spec:active_support:explicit"
|
110
|
+
task :bp => "spec:backports:explicit"
|
111
|
+
task :ex => "spec:extlib:explicit"
|
112
|
+
task :fc => "spec:facets:explicit"
|
113
|
+
end
|
data/lib/monkey.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
module Monkey
|
2
|
+
|
2
3
|
Dir[File.dirname(__FILE__) + "/monkey/*.rb"].sort.each do |path|
|
3
4
|
filename = File.basename(path, '.rb')
|
4
5
|
require "monkey/#{filename}"
|
5
6
|
end
|
7
|
+
|
8
|
+
def self.backend=(backend)
|
9
|
+
Backend.setup! backend
|
10
|
+
backend
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.backend
|
14
|
+
Backend.backend
|
15
|
+
end
|
16
|
+
|
6
17
|
end
|
data/lib/monkey/autoloader.rb
CHANGED
data/lib/monkey/backend.rb
CHANGED
@@ -1,45 +1,110 @@
|
|
1
|
-
require "set"
|
2
|
-
|
3
1
|
module Monkey
|
4
2
|
module Backend
|
5
|
-
|
6
|
-
autoload :ActiveSupport, "monkey/backend/active_support"
|
7
|
-
autoload :BackendDsl, "monkey/backend/backend_dsl"
|
8
|
-
autoload :Backports, "monkey/backend/backports"
|
9
|
-
autoload :Extlib, "monkey/backend/extlib"
|
10
3
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
backend_name ||= expected_name
|
4
|
+
@available_backends = []
|
5
|
+
|
6
|
+
class << self
|
7
|
+
attr_reader :available_backends, :backend
|
16
8
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
9
|
+
|
10
|
+
module AbstractBackend
|
11
|
+
attr_accessor :backend_name, :backend_path
|
12
|
+
|
13
|
+
def available?
|
14
|
+
Object.const_defined? backend_name or $LOADED_FEATURES.any? { |l| l =~ /^#{backend_path}\// }
|
15
|
+
end
|
16
|
+
|
17
|
+
def setup_complete
|
18
|
+
require backend_path
|
19
|
+
setup
|
20
|
+
end
|
21
|
+
|
22
|
+
def load_libs(*data)
|
23
|
+
load_with_prefix backend_path, data
|
24
|
+
end
|
25
|
+
|
26
|
+
def load_with_prefix(prefix, libs = nil)
|
27
|
+
case libs
|
28
|
+
when String, Symbol then require File.join(prefix.to_s, libs.to_s)
|
29
|
+
when Array then libs.each { |lib| load_with_prefix prefix, lib }
|
30
|
+
when Hash then libs.each { |k, v| load_with_prefix File.join(prefix.to_s, k.to_s), v }
|
31
|
+
else raise ArgumentError, "cannot handle #{libs.inspect}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def missing(*libs)
|
36
|
+
load_with_prefix "monkey/backend/common", libs
|
37
|
+
end
|
38
|
+
|
39
|
+
def expects_module(name)
|
40
|
+
name.split("::").inject(Object) do |parent, name|
|
41
|
+
if name.empty?
|
42
|
+
parent
|
43
|
+
else
|
44
|
+
parent.class_eval "module #{name}; self; end"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
20
49
|
end
|
21
50
|
|
22
|
-
def
|
23
|
-
|
51
|
+
def self.new(backend_name, backend_path = nil, &block)
|
52
|
+
mod = eval "module #{backend_name}; self; end"
|
53
|
+
mod.extend AbstractBackend
|
54
|
+
backend_path ||= backend_name.to_s.downcase
|
55
|
+
mod.backend_name, mod.backend_path = backend_name.to_s, backend_path.to_s
|
56
|
+
available_backends << mod
|
57
|
+
mod.class_eval(&block) if block
|
24
58
|
end
|
25
|
-
|
26
|
-
def
|
27
|
-
|
59
|
+
|
60
|
+
def self.preferred_backend
|
61
|
+
available_backends.detect { |b| b.available? } || @backend
|
28
62
|
end
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
def self.add_hook(klass, name)
|
33
|
-
mod = module_for klass
|
34
|
-
mod.class_eval "def #{name}(*a, &b); Monkey::Backend.call(#{klass.name}, #{name}, *a, &b); end"
|
63
|
+
|
64
|
+
def self.setup?
|
65
|
+
!!@setup
|
35
66
|
end
|
36
|
-
|
37
|
-
def self.
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
67
|
+
|
68
|
+
def self.setup!(backend)
|
69
|
+
if backend
|
70
|
+
@backend = detect_backend(backend)
|
71
|
+
@backend.setup
|
72
|
+
@setup = true
|
73
|
+
@backend
|
74
|
+
else
|
75
|
+
available_backends.each do |backend|
|
76
|
+
begin
|
77
|
+
return setup!(backend)
|
78
|
+
rescue LoadError => error
|
79
|
+
@load_error ||= error
|
80
|
+
@backend = nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
raise @load_error
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class << self
|
88
|
+
alias backend= setup!
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.setup
|
92
|
+
setup! preferred_backend unless setup?
|
42
93
|
end
|
43
94
|
|
95
|
+
def self.detect_backend(backend_or_name)
|
96
|
+
return backend_or_name if backend_or_name.respond_to? :setup
|
97
|
+
detected = available_backends.detect do |backend|
|
98
|
+
[backend.backend_name.to_s, backend.backend_path.to_s, backend.name.to_s].include? backend_or_name.to_s
|
99
|
+
end
|
100
|
+
raise ArgumentError, "cannot detect backend #{backend_or_name.inspect}" unless detected
|
101
|
+
detected
|
102
|
+
end
|
103
|
+
|
104
|
+
Dir[File.dirname(__FILE__) + "/backend/*.rb"].sort.each do |path|
|
105
|
+
filename = File.basename(path, '.rb')
|
106
|
+
require "monkey/backend/#{filename}"
|
107
|
+
end
|
108
|
+
|
44
109
|
end
|
45
110
|
end
|
@@ -1,17 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
::String.class_eval do
|
11
|
-
alias to_const_string camelcase
|
12
|
-
alias to_const_path underscore
|
13
|
-
end
|
14
|
-
end
|
1
|
+
Monkey::Backend.new :ActiveSupport, :active_support do
|
2
|
+
def self.setup
|
3
|
+
expects_module "::ActiveSupport::CoreExtensions::String::Inflections"
|
4
|
+
load_libs "core_ext/object" => [:metaclass, :misc], :core_ext => %w[array/extract_options string/inflections module/introspection]
|
5
|
+
Array.send :include, ActiveSupport::CoreExtensions::Array::ExtractOptions
|
6
|
+
Module.send :include, ActiveSupport::CoreExtensions::Module
|
7
|
+
::String.class_eval do
|
8
|
+
alias to_const_string camelcase
|
9
|
+
alias to_const_path underscore
|
15
10
|
end
|
16
|
-
end
|
11
|
+
end
|
17
12
|
end
|
@@ -1,17 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
require "monkey/backend/common/metaclass"
|
10
|
-
::String.class_eval do
|
11
|
-
alias to_const_string camelcase
|
12
|
-
alias to_const_path underscore
|
13
|
-
end
|
14
|
-
end
|
1
|
+
Monkey::Backend.new :Backports do
|
2
|
+
def self.setup
|
3
|
+
load_libs "tools", "1.8.7/kernel", :rails => [:array, :string]
|
4
|
+
missing :parent, :metaclass
|
5
|
+
::String.class_eval do
|
6
|
+
alias camelcase camelize
|
7
|
+
alias to_const_string camelize
|
8
|
+
alias to_const_path underscore
|
15
9
|
end
|
16
10
|
end
|
17
11
|
end
|
@@ -1,12 +1,10 @@
|
|
1
1
|
module Monkey
|
2
2
|
module Backend
|
3
3
|
module Common
|
4
|
-
module
|
5
|
-
::
|
6
|
-
def
|
7
|
-
|
8
|
-
self
|
9
|
-
end
|
4
|
+
module Parent
|
5
|
+
::Module.send :include, self
|
6
|
+
def parent
|
7
|
+
name =~ /^(.+)::[^:]+$/ ? $1.constantize : Object
|
10
8
|
end
|
11
9
|
end
|
12
10
|
end
|
@@ -1,21 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
::Object.class_eval { alias metaclass meta_class }
|
12
|
-
::String.class_eval do
|
13
|
-
alias camelcase to_const_string
|
14
|
-
alias underscore to_const_path
|
15
|
-
def constantize
|
16
|
-
Extlib::Inflection.constantize(self)
|
17
|
-
end
|
18
|
-
end
|
1
|
+
Monkey::Backend.new :Extlib do
|
2
|
+
def self.setup
|
3
|
+
load_libs :object, :string, :inflection
|
4
|
+
missing :parent, :extract_options, :tap
|
5
|
+
::Object.class_eval { alias metaclass meta_class }
|
6
|
+
::String.class_eval do
|
7
|
+
alias camelcase to_const_string
|
8
|
+
alias underscore to_const_path
|
9
|
+
def constantize
|
10
|
+
Extlib::Inflection.constantize(self)
|
19
11
|
end
|
20
12
|
end
|
21
13
|
end
|