maca-arguments 0.4.7.8

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/History.txt ADDED
@@ -0,0 +1,13 @@
1
+ == 0.4 2009-06-30
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
5
+ * Works with Ruby 1.8.6 and 1.9.1
6
+
7
+ == 0.4.2 2009-07-03
8
+
9
+ * Fixed a Bug where not passing arguments would rise try to call #key? on nil
10
+
11
+ == 0.4.3 2009-07-07
12
+
13
+ * Fixed a serious Bug where default values could not be overriden by passing arguments without keyword
data/Manifest.txt ADDED
@@ -0,0 +1,10 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ lib/arguments.rb
6
+ lib/arguments/class.rb
7
+ lib/arguments/mri.rb
8
+ lib/arguments/vm.rb
9
+ spec/arguments_spec.rb
10
+ spec/klass.rb
data/README.rdoc ADDED
@@ -0,0 +1,92 @@
1
+ = arguments
2
+
3
+ Keyword arguments support now!
4
+
5
+ == DESCRIPTION:
6
+
7
+ You don't have to wait until Ruby 2.0 to get (named|keyword) arguments support.
8
+ Arguments has been tested with Ruby 1.8.6 and ruby 1.9.1 and eventually will work with JRuby (if someone is interested in contributing, I guess is possible since merb-action-args works with JRuby)
9
+
10
+ == SYNOPSIS:
11
+
12
+ require 'arguments'
13
+
14
+ class Example
15
+ def meth(a = :a, b = :b, c = :c)
16
+ [a,b,c]
17
+ end
18
+
19
+ named_args_for :meth
20
+
21
+ class << self
22
+ def class_method(a = :a, b = :b, c = :c)
23
+ [a,b,c]
24
+ end
25
+ named_args_for :class_method
26
+ end
27
+ end
28
+
29
+ nu = Example.new
30
+ nu.meth #=> [:a,:b,:c]
31
+ nu.meth(1, :c => Class) #=> [1,:b,Class]
32
+ nu.meth(:b => nil, :a => 'something') #=> ['something', nil, :c]
33
+
34
+ Example.class_method(:b => nil, :a => 'something') #=> ['something', nil, :c]
35
+
36
+
37
+
38
+ * #named_arguments_for is aliased as #named_args_for and #named_args
39
+ * Calling #named_args_for without arguments patches all previously declared methods in scope
40
+ * Any number of method names (Symbol or String) corresponding to existing methods can be passed
41
+ * Methods with no optionals won't be patched (will behave as usual with no named params)
42
+ * Same for methods with splatted arguments and for native methods (not declared in Ruby)
43
+ * Keyword argument take precedence over argument order:
44
+
45
+ nu.meth(10, :a => -10) #=> [-10, :b, :c]
46
+
47
+
48
+ == LIMITATIONS
49
+
50
+ * Performance penalty occurs only in 1.8.6 due to ParseTree use and only while calling Class#named_args\_for, penalty while calling the actuall method is neglectable.
51
+ * With Ruby 1.8.6 it can patch methods declared with eval, with 1.9.1 only methods declared in a source file.
52
+ * If last argument is a Hash is taken as an options Hash and not assigned to the argument varible, if you want to pass a has as a last argument use keywords.
53
+
54
+ == TODO
55
+
56
+ Don't use last argument (Hash) as options if passed total number of args.
57
+
58
+ == REQUIREMENTS:
59
+
60
+ Ruby 1.8.6:
61
+
62
+ - ParseTree >= 3.0.3
63
+ - Ruby2Ruby 1.1.9
64
+
65
+ == INSTALL:
66
+
67
+ sudo gem install maca-arguments –source http://gems.github.com
68
+
69
+ == LICENSE:
70
+
71
+ (The MIT License)
72
+
73
+ Copyright (c) 2009 Macario Ortega
74
+
75
+ Permission is hereby granted, free of charge, to any person obtaining
76
+ a copy of this software and associated documentation files (the
77
+ 'Software'), to deal in the Software without restriction, including
78
+ without limitation the rights to use, copy, modify, merge, publish,
79
+ distribute, sublicense, and/or sell copies of the Software, and to
80
+ permit persons to whom the Software is furnished to do so, subject to
81
+ the following conditions:
82
+
83
+ The above copyright notice and this permission notice shall be
84
+ included in all copies or substantial portions of the Software.
85
+
86
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
87
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
88
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
89
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
90
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
91
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
92
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen hoe].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/arguments'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.new('arguments', Arguments::VERSION) do |p|
7
+ p.developer('Macario Ortega', 'macarui@gmail.com')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ # p.rubyforge_name = p.name # TODO this is default value
10
+
11
+ p.extra_deps = [
12
+ ['ParseTree','>= 3.0.3'],
13
+ ['ruby2ruby', '= 1.1.9']
14
+ ]
15
+
16
+ p.extra_dev_deps = [
17
+ ['newgem', ">= #{::Newgem::VERSION}"]
18
+ ]
19
+
20
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
21
+ # path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
22
+ # p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
23
+ p.rsync_args = '-av --delete --ignore-errors'
24
+ end
25
+
26
+ require 'newgem/tasks' # load /tasks/*.rake
27
+ Dir['tasks/**/*.rake'].each { |t| load t }
28
+
29
+ # TODO - want other tests/tasks run by default? Add them to the list
30
+ # task :default => [:spec, :features]
data/lib/arguments.rb ADDED
@@ -0,0 +1,11 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
+
3
+ require 'arguments/class'
4
+
5
+
6
+
7
+ RUBY_VERSION.to_f >= 1.9 ? require( 'arguments/vm' ) : require( 'arguments/mri' )
8
+
9
+ module Arguments
10
+ VERSION = '0.4.7'
11
+ end
@@ -0,0 +1,72 @@
1
+ module NamedArgs
2
+ def named_arguments_for *methods
3
+ methods = instance_methods - Object.methods if methods.empty?
4
+
5
+ methods.each do |meth|
6
+ if(meth.to_s.include?('.'))
7
+ # they may have passed in a parameter like :klass.method for a class method
8
+ klass, meth = meth.to_s.split('.')
9
+ klass = eval(klass) # from "Klass" to Klass
10
+ klass = (class << klass; self; end)
11
+ names = Arguments.names klass, meth
12
+ else
13
+ names = Arguments.names self, meth
14
+ klass = self
15
+ end
16
+ next if names.empty? || names.any?{|name| name[0] == :"*args"}
17
+
18
+ assigns = []
19
+ names.each_with_index do |name, index|
20
+ unless name.size == 1
21
+ # optionals
22
+ assigns << <<-RUBY_EVAL
23
+ #{ name.first } =
24
+ if opts.key?(:#{ name.first })
25
+ opts[:#{ name.first }]
26
+ else
27
+ args.size >= #{ index + 1 } ? args[#{ index }] : #{ name.last }
28
+ end
29
+ RUBY_EVAL
30
+ else
31
+ # requireds
32
+ assigns << <<-RUBY_EVAL
33
+ begin
34
+ #{ name.first } = opts.key?(:#{ name.first }) ? opts[:#{ name.first }] : args.fetch(#{ index })
35
+ rescue
36
+ raise ArgumentError.new('passing `#{ name.first }` is required')
37
+ end
38
+ RUBY_EVAL
39
+ end
40
+ end
41
+
42
+ line_loc = __LINE__
43
+ new_code = <<-RUBY_EVAL
44
+ def __new_#{ meth } *args, &block
45
+ opts = args.last.kind_of?( Hash ) ? args.pop : {}
46
+ #{ assigns.join("\n") }
47
+ __original_#{ meth } #{ names.collect{ |n| n.first }.join(', ') }, &block
48
+ end
49
+
50
+ alias __original_#{ meth } #{ meth }
51
+ alias #{ meth } __new_#{ meth }
52
+ RUBY_EVAL
53
+
54
+ puts "wrapping #{ meth } with this code #{new_code}" if $VERBOSE
55
+
56
+ begin
57
+ klass.module_eval new_code, __FILE__ + '.approximately', line_loc + 1
58
+ rescue SyntaxError => e
59
+ puts "warning--unable to wrap method #{ meth } -- possibly a syntax exception or it's not all on one line in 1.9 -- #{new_code}"
60
+ throw e
61
+ end
62
+
63
+ end
64
+ end
65
+
66
+ alias :named_args_for :named_arguments_for
67
+ alias :named_args :named_arguments_for
68
+
69
+ end
70
+
71
+ class Class; include NamedArgs; end
72
+ class Module; include NamedArgs; end
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ gem 'ParseTree', '>= 3.0.3'
3
+ require 'parse_tree'
4
+
5
+ gem 'ruby2ruby', '= 1.1.9'
6
+ require 'ruby2ruby'
7
+
8
+ module Arguments
9
+ def self.names klass, method
10
+ args = ParseTree.translate( klass, method ).assoc(:scope).assoc(:block).assoc(:args)
11
+ args = args[1..-1]
12
+ return [] if args.empty?
13
+ if args.last.instance_of? Array
14
+ vals = args.pop[1..-1]
15
+ else
16
+ # if it has no optionals then vals is empty
17
+ vals = []
18
+ end
19
+
20
+ args.collect do |arg|
21
+ if val = vals.find{ |v| v[1] == arg }
22
+ [arg, Ruby2Ruby.new.process(val.last)]
23
+ else
24
+ [arg]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+
2
+ module Arguments
3
+ def self.names klass, method
4
+ source, line = klass.instance_method( method ).source_location rescue klass.method( method ).source_location
5
+ return [] unless source and line
6
+ str = IO.readlines(source)[ line - 1 ]
7
+ return [] if str.match(/\*\w+/)
8
+ throw 'poor comma' + str if str =~ /,\W*&/
9
+ str.match(/def\s*\w+\s*\(?\s*([^)\n]*)/)[1] #This could look better
10
+ .scan(/(\w+)(?:\s*=\s*([^,]+))|(\w+)/).map{ |e| e.compact }.collect{|e2| e2[1].gsub!(/\W*\&.*/, '') if e2[1]; e2}
11
+ end
12
+ end
@@ -0,0 +1,142 @@
1
+ require "#{ File.dirname __FILE__ }/../lib/arguments"
2
+ require 'benchmark'
3
+
4
+ describe Arguments do
5
+
6
+ before do
7
+ Object.send(:remove_const, 'Klass') rescue nil
8
+ load "#{ File.dirname __FILE__ }/klass.rb"
9
+ load "#{ File.dirname __FILE__ }/module.rb"
10
+ @instance = Klass.new
11
+ end
12
+
13
+ it "should respond to named_arguments" do
14
+ Klass.send( :named_arguments_for, :three )
15
+ end
16
+
17
+ it "should not respond to named_arguments" do
18
+ lambda { Klass.new.send( :named_arguments_for ) }.should raise_error( NoMethodError )
19
+ end
20
+
21
+ it "should get argument names with literals" do
22
+ Arguments.names( Klass, :two ).collect{ |a, b| [a.to_sym, b].compact }.
23
+ should == [[:one], [:two, "2"], [:three, "Klass.new"]]
24
+ end
25
+
26
+ it "shouldn't break defaults" do
27
+ @instance.two(1).should == [1, 2, Klass.new]
28
+ end
29
+
30
+ it "should allow passing named argument" do
31
+ Klass.send( :named_arguments_for, :two )
32
+ @instance.two(1, :three => 3).should == [1, 2, 3]
33
+ end
34
+
35
+ it "should raise ArgumentError if not passing required params" do
36
+ Klass.send( :named_arguments_for, :two )
37
+ lambda { @instance.two( :three => 3 ) }.should raise_error(ArgumentError)
38
+ end
39
+
40
+ it "should override passed value with hash" do
41
+ Klass.send( :named_arguments_for, :two )
42
+ @instance.two( :one => nil ).should == [nil, 2, Klass.new]
43
+ end
44
+
45
+ it "should allow overriding with nil" do
46
+ Klass.send( :named_arguments_for, :two )
47
+ @instance.two( 1, :three => nil ).should == [1, 2, nil]
48
+ end
49
+
50
+ it "should pass block" do
51
+ Klass.send( :named_arguments_for, :with_block )
52
+ @instance.with_block( 1, :three => nil, :two => 'something' ){ :block }.should == [1, 'something', nil, :block]
53
+ end
54
+
55
+ it "should override defaults on standard passing" do
56
+ Klass.send( :named_arguments_for, :asr )
57
+ @instance.asr(0, 1, 2, :curve => 3).should == [0,1,2,3]
58
+ end
59
+
60
+ it "should work with methods that have no optionals" do
61
+ Klass.send( :named_arguments_for, :go5 )
62
+ @instance.go5(1, 2).should == [1,2]
63
+ @instance.go5(1, :b => 3).should == [1,3]
64
+ @instance.go5(:a => 4, :b => 5).should == [4, 5]
65
+ end
66
+
67
+ it "should work with class methods" do
68
+ Klass.asr(0, 1, 2, :curve => 3).should == [0,1,2,3]
69
+ end
70
+
71
+ it "should work with class methods" do
72
+ Klass.send( :named_arguments_for, :"Klass.class_method")
73
+ Klass.class_method(:a => 1).should == 1
74
+ end
75
+
76
+ it "should work with class methods called like :self.method_name" do
77
+ Klass.send( :named_arguments_for, :"self.class_method2")
78
+ Klass.class_method2(:a => 1).should == 1
79
+ end
80
+
81
+ it "should work with class methods passed in by string instead of symboL" do
82
+ Klass.send( :named_arguments_for, "self.class_method3")
83
+ Klass.class_method3(:a => 1).should == 1
84
+ end
85
+
86
+ it "should not patch methods that accept no args" do
87
+ # Arguments.should_not_receive(:names)
88
+ Klass.send( :named_arguments_for, :no_args )
89
+ lambda { @instance.no_args(1) }.should raise_error(ArgumentError)
90
+ @instance.no_args.should be_nil
91
+ end
92
+
93
+ it "should not patch methods that use splatter op" do
94
+ Klass.send( :named_arguments_for, :splatted )
95
+ @instance.splatted(1, :args => 1).should == [1, {:args => 1}]
96
+
97
+ Klass.send( :named_arguments_for, :splatted2 )
98
+ @instance.splatted2(:a => 1, :"*args" => 3).should == []
99
+
100
+ Klass.send( :named_arguments_for, :splatted3 )
101
+ @instance.splatted3(:a => 1, :"*args" => 3).should == []
102
+ @instance.splatted3(1, :b => 2, :args => 1).should == [{:b => 2, :args => 1}]
103
+
104
+ Klass.send( :named_arguments_for, :splatted4 )
105
+ @instance.splatted4(1, :b => 2, :args => 1).should == []
106
+
107
+ end
108
+
109
+ it "should patch methods with no optionals" do
110
+ Klass.send( :named_arguments_for, :no_opts )
111
+ lambda { @instance.no_opts(1,2, :a => 1)}.should raise_error(ArgumentError)
112
+ @instance.no_opts(1,2, :c => 1).should == 1
113
+ end
114
+
115
+ it "should patch all methods" do
116
+ Klass.send( :named_args )
117
+ end
118
+
119
+ it "should benchmark without hack" do
120
+ puts Benchmark.measure {
121
+ 1_000.times do
122
+ @instance.with_block( 1, :three => nil ){ :block }
123
+ end
124
+ }
125
+ end
126
+
127
+ it "should work with modules too" do
128
+ TestMod.send( :named_arguments_for, :go)
129
+ IncludesTestMod.new.go(:a => 1).should == 1
130
+ end
131
+
132
+ it "should benchmark with hack" do
133
+ puts Benchmark.measure {
134
+ Klass.send( :named_arguments_for, :with_block )
135
+ }
136
+ puts Benchmark.measure {
137
+ 1_000.times do
138
+ @instance.with_block( 1, :three => nil ){ :block }
139
+ end
140
+ }
141
+ end
142
+ end
data/spec/klass.rb ADDED
@@ -0,0 +1,68 @@
1
+ class Klass
2
+ def three one = 1, two = 2, three = 3
3
+ [one, two, three]
4
+ end
5
+
6
+ def two one, two = 2, three = Klass.new
7
+ [one, two, three]
8
+ end
9
+
10
+ def with_block one, two = 2, three = 3
11
+ [one, two, three, yield]
12
+ end
13
+
14
+
15
+ def go5(a, b)
16
+ [a, b]
17
+ end
18
+
19
+ def asr attackTime = 3, sustainLevel = 2, releaseTime = 1, curve = 0
20
+ [attackTime, sustainLevel, releaseTime, curve]
21
+ end
22
+
23
+ def no_args
24
+ end
25
+
26
+ def splatted *args
27
+ args
28
+ end
29
+
30
+ def splatted2 a=1, *args
31
+ args
32
+ end
33
+
34
+ def splatted3 a, *args
35
+ args
36
+ end
37
+
38
+ def splatted4 a, b=1, *args
39
+ args
40
+ end
41
+
42
+ def no_opts a, b, c
43
+ c
44
+ end
45
+
46
+ class << self
47
+ def asr attackTime = 3, sustainLevel = 2, releaseTime = 1, curve = 0
48
+ [attackTime, sustainLevel, releaseTime, curve]
49
+ end
50
+ named_arguments_for :asr
51
+
52
+ def class_method(a)
53
+ a
54
+ end
55
+
56
+ def class_method2(a)
57
+ a
58
+ end
59
+
60
+ def class_method3(a)
61
+ a
62
+ end
63
+ end
64
+
65
+ def == other
66
+ self.class == other.class
67
+ end
68
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: maca-arguments
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.7.8
5
+ platform: ruby
6
+ authors:
7
+ - Macario Ortega
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-03 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ParseTree
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 3.0.3
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: ruby2ruby
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.1.9
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: newgem
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.4.1
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: rspec
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 1.2.7
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: hoe
57
+ type: :development
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 1.8.0
64
+ version:
65
+ description: You don't have to wait until Ruby 2.0 to get (named|keyword) arguments support. Arguments has been tested with Ruby 1.8.6 and ruby 1.9.1 and eventually will work with JRuby
66
+ email:
67
+ - macarui@gmail.com
68
+ executables: []
69
+
70
+ extensions: []
71
+
72
+ extra_rdoc_files:
73
+ - History.txt
74
+ - Manifest.txt
75
+ - README.rdoc
76
+ files:
77
+ - History.txt
78
+ - Manifest.txt
79
+ - README.rdoc
80
+ - Rakefile
81
+ - lib/arguments.rb
82
+ - lib/arguments/class.rb
83
+ - lib/arguments/mri.rb
84
+ - lib/arguments/vm.rb
85
+ - spec/arguments_spec.rb
86
+ - spec/klass.rb
87
+ has_rdoc: true
88
+ homepage:
89
+ licenses:
90
+ post_install_message:
91
+ rdoc_options:
92
+ - --main
93
+ - README.rdoc
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: "0"
101
+ version:
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: "0"
107
+ version:
108
+ requirements: []
109
+
110
+ rubyforge_project: arguments
111
+ rubygems_version: 1.3.5
112
+ signing_key:
113
+ specification_version: 2
114
+ summary: You don't have to wait until Ruby 2.0 to get (named|keyword) arguments support
115
+ test_files: []
116
+