rubyless 0.3.2 → 0.3.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.
- data/History.txt +5 -0
- data/lib/processor.rb +2 -2
- data/lib/rubyless.rb +1 -1
- data/lib/safe_class.rb +16 -19
- data/rubyless.gemspec +2 -2
- data/test/RubyLess/basic.yml +5 -1
- data/test/RubyLess/errors.yml +6 -2
- data/test/RubyLess_test.rb +10 -5
- data/test/mock/dummy_class.rb +9 -8
- metadata +2 -2
data/History.txt
CHANGED
data/lib/processor.rb
CHANGED
@@ -210,8 +210,8 @@ module RubyLess
|
|
210
210
|
|
211
211
|
def get_method(signature, receiver, is_method = true)
|
212
212
|
res = receiver.respond_to?(:safe_method_type) ? receiver.safe_method_type(signature) : SafeClass.safe_method_type_for(receiver, signature)
|
213
|
-
res = res.call(@helper) if res.kind_of?(Proc)
|
214
|
-
res
|
213
|
+
res = res.call(@helper, signature) if res.kind_of?(Proc)
|
214
|
+
res.kind_of?(Symbol) ? nil : res # Symbols not allowed here (should be resolved in receiver.safe_method_type)
|
215
215
|
end
|
216
216
|
end
|
217
217
|
end
|
data/lib/rubyless.rb
CHANGED
data/lib/safe_class.rb
CHANGED
@@ -10,11 +10,7 @@ module RubyLess
|
|
10
10
|
|
11
11
|
# Return method type (options) if the given signature is a safe method for the class.
|
12
12
|
def self.safe_method_type_for(klass, signature)
|
13
|
-
|
14
|
-
res.dup
|
15
|
-
else
|
16
|
-
nil
|
17
|
-
end
|
13
|
+
safe_methods_for(klass)[signature]
|
18
14
|
end
|
19
15
|
|
20
16
|
# Declare a safe method for a given class
|
@@ -65,7 +61,7 @@ module RubyLess
|
|
65
61
|
if v.kind_of?(Hash)
|
66
62
|
v = defaults.merge(v)
|
67
63
|
v[:method] = v[:method] ? v[:method].to_s : k.first.to_s
|
68
|
-
elsif v.kind_of?(Proc)
|
64
|
+
elsif v.kind_of?(Proc) || v.kind_of?(Symbol)
|
69
65
|
# cannot merge defaults
|
70
66
|
else
|
71
67
|
v = defaults.merge(:class => v, :method => k.first.to_s)
|
@@ -106,22 +102,21 @@ module RubyLess
|
|
106
102
|
SafeClass.safe_methods_for(self)
|
107
103
|
end
|
108
104
|
|
109
|
-
# Return
|
105
|
+
# Return the type if the given signature corresponds to a safe method for the class.
|
110
106
|
def self.safe_method_type(signature)
|
111
|
-
|
112
|
-
res.dup # TODO: replace by freeze
|
113
|
-
else
|
114
|
-
nil
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# Return the method type (options) if the given signature is a safe method for the class.
|
119
|
-
def safe_method_type(signature)
|
120
|
-
self.class.safe_method_type(signature)
|
107
|
+
SafeClass.safe_method_type_for(self, signature)
|
121
108
|
end
|
122
109
|
end # base.class_eval
|
123
110
|
end # included
|
124
111
|
|
112
|
+
|
113
|
+
# Return the type if the given signature corresponds to a safe method for the object's class.
|
114
|
+
def safe_method_type(signature)
|
115
|
+
if type = self.class.safe_method_type(signature)
|
116
|
+
type.kind_of?(Symbol) ? self.send(type, signature) : type
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
125
120
|
# Safe attribute reader used when 'safe_readable?' could not be called because the class
|
126
121
|
# is not known during compile time.
|
127
122
|
def safe_read(key)
|
@@ -135,12 +130,14 @@ module RubyLess
|
|
135
130
|
(@@_safe_methods[klass] || {}).map do |signature, return_value|
|
136
131
|
if return_value.kind_of?(Hash)
|
137
132
|
return_value[:class] = parse_class(return_value[:class])
|
138
|
-
elsif
|
133
|
+
elsif return_value.kind_of?(Proc) || return_value.kind_of?(Symbol)
|
134
|
+
# keep
|
135
|
+
else
|
139
136
|
return_value = {:class => return_value}
|
140
137
|
end
|
141
138
|
method = signature.shift
|
142
139
|
signature = [method] + signature.map {|e| parse_class(e)}
|
143
|
-
list[signature] = return_value
|
140
|
+
list[signature] = return_value.freeze
|
144
141
|
end
|
145
142
|
list
|
146
143
|
end
|
data/rubyless.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{rubyless}
|
5
|
-
s.version = "0.3.
|
5
|
+
s.version = "0.3.3"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Gaspard Bucher"]
|
9
|
-
s.date = %q{2009-10-
|
9
|
+
s.date = %q{2009-10-26}
|
10
10
|
s.description = %q{RubyLess is an interpreter for "safe ruby". The idea is to transform some "unsafe" ruby code into safe, type checked
|
11
11
|
ruby, eventually rewriting some variables or methods.}
|
12
12
|
s.email = %q{gaspard@teti.ch}
|
data/test/RubyLess/basic.yml
CHANGED
data/test/RubyLess/errors.yml
CHANGED
@@ -10,7 +10,7 @@ zero_div:
|
|
10
10
|
src: "1/(id-10)"
|
11
11
|
tem: "(1/(var1.zip-10) rescue nil)"
|
12
12
|
res: ""
|
13
|
-
|
13
|
+
|
14
14
|
looping:
|
15
15
|
src: "while(true) do puts 'flood' end"
|
16
16
|
res: 'Bug! Unknown node-type :while to RubyLess::RubyLessProcessor'
|
@@ -29,4 +29,8 @@ number_argument:
|
|
29
29
|
|
30
30
|
string_argument:
|
31
31
|
src: "dictionary[spouse.name]"
|
32
|
-
res: "'get_dict' does not respond to '[](String)'."
|
32
|
+
res: "'get_dict' does not respond to '[](String)'."
|
33
|
+
|
34
|
+
symbol_type_not_used_out_of_helper:
|
35
|
+
src: "node.foo"
|
36
|
+
res: "'var1' does not respond to 'foo()'."
|
data/test/RubyLess_test.rb
CHANGED
@@ -12,28 +12,33 @@ class SimpleHelper < Test::Unit::TestCase
|
|
12
12
|
include RubyLess::SafeClass
|
13
13
|
safe_method :prev => {:class => Dummy, :method => 'previous'}
|
14
14
|
safe_method :main => {:class => Dummy, :method => '@node'}
|
15
|
-
safe_method :node => lambda {|h| {:class => h.context[:node_class], :method => h.context[:node]}}
|
15
|
+
safe_method :node => lambda {|h, s| {:class => h.context[:node_class], :method => h.context[:node]}}
|
16
16
|
safe_method :now => {:class => Time, :method => "Time.now"}
|
17
17
|
safe_method :birth => {:class => Time, :method => "Date.parse('2009-06-02 18:44')"}
|
18
18
|
safe_method 'dictionary' => {:class => StringDictionary, :method => 'get_dict'}
|
19
19
|
safe_method [:vowel_count, String] => Number
|
20
20
|
safe_method [:log_info, Dummy, String] => String
|
21
|
+
safe_method :foo => :contextual_method, :bar => :contextual_method
|
21
22
|
safe_method_for String, [:==, String] => Boolean
|
22
23
|
safe_method_for String, [:to_s] => String
|
23
24
|
safe_method_for Time, [:strftime, String] => String
|
24
25
|
|
25
26
|
# Example to dynamically rewrite method calls during compilation
|
26
27
|
def safe_method_type(signature)
|
27
|
-
unless res =
|
28
|
+
unless res = super
|
28
29
|
# try to execute method in the current var "var.method"
|
29
30
|
if res = context[:node_class].safe_method_type(signature)
|
30
|
-
res = res.call(self) if res.kind_of?(Proc)
|
31
|
-
res
|
31
|
+
res = res.call(self, signature) if res.kind_of?(Proc)
|
32
|
+
res = res.merge(:method => "#{context[:node]}.#{res[:method] || signature[0]}")
|
32
33
|
end
|
33
34
|
end
|
34
35
|
res
|
35
36
|
end
|
36
37
|
|
38
|
+
def contextual_method(signature)
|
39
|
+
{:method => "contextual_#{signature[0]}", :class => String}
|
40
|
+
end
|
41
|
+
|
37
42
|
def var1
|
38
43
|
Dummy.new
|
39
44
|
end
|
@@ -75,7 +80,7 @@ class SimpleHelper < Test::Unit::TestCase
|
|
75
80
|
rescue => err
|
76
81
|
# puts "\n\n#{err.message}"
|
77
82
|
# puts err.backtrace
|
78
|
-
|
83
|
+
err.message
|
79
84
|
end
|
80
85
|
|
81
86
|
yt_make
|
data/test/mock/dummy_class.rb
CHANGED
@@ -3,37 +3,38 @@ require File.dirname(__FILE__) + '/active_record_mock'
|
|
3
3
|
class Dummy < RubyLess::ActiveRecordMock
|
4
4
|
attr_reader :name
|
5
5
|
include RubyLess::SafeClass
|
6
|
-
|
6
|
+
|
7
7
|
safe_method [:ancestor?, Dummy] => Boolean
|
8
8
|
safe_method :parent => {:class => 'Dummy', :special_option => 'foobar'},
|
9
9
|
:children => ['Dummy'],
|
10
10
|
:project => 'Dummy',
|
11
11
|
:id => {:class => Number, :method => :zip},
|
12
|
-
:name => String
|
12
|
+
:name => String,
|
13
|
+
:foo => :bar
|
13
14
|
safe_method :defaults => {:nil => true},
|
14
15
|
:spouse => 'Dummy',
|
15
16
|
:husband => {:class => 'Dummy'}
|
16
|
-
|
17
|
+
|
17
18
|
safe_attribute :age, :friend_id, :log_at, :format
|
18
|
-
|
19
|
+
|
19
20
|
def initialize(name = 'dummy')
|
20
21
|
@name = name
|
21
22
|
end
|
22
|
-
|
23
|
+
|
23
24
|
# This method returns pseudo-nil and does not need to be declared with :nil => true
|
24
25
|
def project
|
25
26
|
Dummy.new('project')
|
26
27
|
end
|
27
|
-
|
28
|
+
|
28
29
|
# This method can return nil and must be declared with :nil => true
|
29
30
|
def spouse
|
30
31
|
nil
|
31
32
|
end
|
32
|
-
|
33
|
+
|
33
34
|
def husband
|
34
35
|
nil
|
35
36
|
end
|
36
|
-
|
37
|
+
|
37
38
|
def zip
|
38
39
|
10
|
39
40
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubyless
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gaspard Bucher
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-10-
|
12
|
+
date: 2009-10-26 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|