otaku 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/HISTORY.txt +19 -0
- data/VERSION +1 -1
- data/lib/otaku.rb +4 -1
- data/lib/otaku/handler.rb +84 -61
- data/lib/otaku/server.rb +4 -3
- data/otaku.gemspec +2 -2
- data/spec/handler_spec.rb +26 -8
- data/spec/integration_spec.rb +12 -2
- metadata +4 -4
data/.gitignore
CHANGED
data/HISTORY.txt
CHANGED
@@ -1,5 +1,24 @@
|
|
1
|
+
=== 0.2.2 2010-07-21
|
2
|
+
|
3
|
+
= Features
|
4
|
+
* $LOAD_PATH include the directory where the file calling Otaku.start is located, thus
|
5
|
+
user no longer need to verbosely define the full path of the file to require [#ngty]
|
6
|
+
|
7
|
+
= Maintenance
|
8
|
+
* magic variable __FILE__ is now derived the same way as __LINE__ (see below) [#ngty]
|
9
|
+
|
10
|
+
= Bug Fixes
|
11
|
+
* magic variable __LINE__ now works as expected (the line where the proc is defined in file,
|
12
|
+
instead of the string eval line) [#ngty]
|
13
|
+
* fixed unexpected failure in specs as a result of using installed otaku, instead of the
|
14
|
+
one under current project directory (by passing -I when running the sub-process server
|
15
|
+
script) [#ngty]
|
16
|
+
|
1
17
|
=== 0.2.1 2010-07-19
|
2
18
|
|
19
|
+
= Maintenance
|
20
|
+
* logging support is moved directly under Otaku module [#ngty]
|
21
|
+
|
3
22
|
= Bug Fixes
|
4
23
|
* closing of logger is done ONLY if the logger has been initialized [#ngty]
|
5
24
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.2
|
data/lib/otaku.rb
CHANGED
@@ -5,7 +5,6 @@ require 'base64'
|
|
5
5
|
require 'ruby2ruby'
|
6
6
|
require 'ruby_parser'
|
7
7
|
|
8
|
-
# $LOAD_PATH.unshift(File.dirname(__FILE__))
|
9
8
|
require 'otaku/encoder'
|
10
9
|
require 'otaku/handler'
|
11
10
|
require 'otaku/server'
|
@@ -39,6 +38,10 @@ module Otaku
|
|
39
38
|
end
|
40
39
|
end
|
41
40
|
|
41
|
+
def root
|
42
|
+
File.expand_path(File.dirname(__FILE__))
|
43
|
+
end
|
44
|
+
|
42
45
|
def start(context = {}, &handler)
|
43
46
|
raise HandlerNotDefinedError unless block_given?
|
44
47
|
Server.handler = Handler.new(context, handler)
|
data/lib/otaku/handler.rb
CHANGED
@@ -3,11 +3,17 @@ module Otaku
|
|
3
3
|
|
4
4
|
def initialize(context, handler)
|
5
5
|
@context = __context_as_code__(context)
|
6
|
-
|
6
|
+
magic_proc = MagicProc.new(handler)
|
7
|
+
@proc, @file, @line = [:code, :file, :line].map{|meth| magic_proc.send(meth) }
|
7
8
|
end
|
8
9
|
|
9
|
-
def
|
10
|
-
eval(@context
|
10
|
+
def process(data)
|
11
|
+
(instance = eval(@context, nil, '(generated class)', 1)).
|
12
|
+
instance_exec(data, &(block = eval(@proc, nil, @file, @line)))
|
13
|
+
end
|
14
|
+
|
15
|
+
def root
|
16
|
+
File.dirname(@file)
|
11
17
|
end
|
12
18
|
|
13
19
|
private
|
@@ -19,81 +25,98 @@ module Otaku
|
|
19
25
|
end.sort.join('; ')
|
20
26
|
end
|
21
27
|
|
22
|
-
def __proc_as_code__(block)
|
23
|
-
MagicProc.new(block).to_code
|
24
|
-
end
|
25
|
-
|
26
28
|
class MagicProc
|
27
29
|
|
28
30
|
RUBY_PARSER = RubyParser.new
|
29
31
|
RUBY_2_RUBY = Ruby2Ruby.new
|
30
32
|
|
33
|
+
attr_reader :file, :line, :code
|
34
|
+
|
31
35
|
def initialize(block)
|
32
36
|
@block = block
|
37
|
+
extract_file_and_line_and_code
|
33
38
|
end
|
34
39
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
private
|
41
|
+
|
42
|
+
def extract_file_and_line_and_code
|
43
|
+
code, remaining = code_fragments
|
44
|
+
|
45
|
+
while frag = remaining[frag_regexp,1]
|
46
|
+
begin
|
47
|
+
sexp = RUBY_PARSER.parse(replace_magic_vars(code += frag))
|
48
|
+
if sexp.inspect =~ sexp_regexp
|
49
|
+
@code = revert_magic_vars(RUBY_2_RUBY.process(sexp)).sub('proc {','lambda {')
|
50
|
+
break
|
51
|
+
end
|
52
|
+
rescue SyntaxError, Racc::ParseError, NoMethodError
|
53
|
+
remaining.sub!(frag,'')
|
54
|
+
end
|
44
55
|
end
|
45
56
|
end
|
46
|
-
end
|
47
57
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
58
|
+
def code_fragments
|
59
|
+
ignore, start_marker, arg =
|
60
|
+
[:ignore, :start_marker, :arg].map{|key| code_match_args[key] }
|
61
|
+
[
|
62
|
+
"proc #{start_marker} |#{arg}| ",
|
63
|
+
source_code.sub(ignore, '')
|
64
|
+
]
|
65
|
+
end
|
56
66
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
67
|
+
def sexp_regexp
|
68
|
+
@sexp_regexp ||= (
|
69
|
+
Regexp.new([
|
70
|
+
Regexp.quote("s(:iter, s(:call, nil, :"),
|
71
|
+
"(proc|lambda)",
|
72
|
+
Regexp.quote(", s(:arglist)), s(:lasgn, :#{code_match_args[:arg]}), s("),
|
73
|
+
].join)
|
74
|
+
)
|
75
|
+
end
|
66
76
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
77
|
+
def frag_regexp
|
78
|
+
@frag_regexp ||= (
|
79
|
+
end_marker = {'do' => 'end', '{' => '\}'}[code_match_args[:start_marker]]
|
80
|
+
/^(.*?\W#{end_marker})/m
|
81
|
+
)
|
82
|
+
end
|
73
83
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
84
|
+
def code_regexp
|
85
|
+
@code_regexp ||=
|
86
|
+
/^(.*?(Otaku\.start.*?|lambda|proc|Proc\.new)\s*(do|\{)\s*\|(\w+)\|\s*)/m
|
87
|
+
end
|
78
88
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
+
def code_match_args
|
90
|
+
@code_match_args ||= (
|
91
|
+
args = source_code.match(code_regexp)
|
92
|
+
{
|
93
|
+
:ignore => args[1],
|
94
|
+
:start_marker => args[3],
|
95
|
+
:arg => args[4]
|
96
|
+
}
|
97
|
+
)
|
98
|
+
end
|
89
99
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
100
|
+
def source_code
|
101
|
+
@source_code ||= (
|
102
|
+
file, line = /^#<Proc:0x[0-9A-Fa-f]+@(.+):(\d+).*?>$/.match(@block.inspect)[1..2]
|
103
|
+
@file = File.expand_path(file)
|
104
|
+
@line = line.to_i
|
105
|
+
File.readlines(@file)[@line.pred .. -1].join
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
def replace_magic_vars(code)
|
110
|
+
%w{__FILE__ __LINE__}.inject(code) do |code, var|
|
111
|
+
code.gsub(var, "%|((#{var}))|")
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def revert_magic_vars(code)
|
116
|
+
%w{__FILE__ __LINE__}.inject(code) do |code, var|
|
117
|
+
code.gsub(%|"((#{var}))"|, var)
|
118
|
+
end
|
119
|
+
end
|
97
120
|
|
98
121
|
end
|
99
122
|
|
data/lib/otaku/server.rb
CHANGED
@@ -20,9 +20,10 @@ module Otaku
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def run_server_script
|
23
|
-
script = File.join(
|
23
|
+
script = File.join(Otaku.root, 'otaku.rb')
|
24
24
|
args = Encoder.encode(:config => Otaku.config, :handler => @handler)
|
25
|
-
|
25
|
+
load_paths = [@handler.root, Otaku.root].join(' -I')
|
26
|
+
@process = IO.popen(%|#{Otaku.ruby} -I#{load_paths} #{script} "#{args.gsub('"','\"')}"|,'r')
|
26
27
|
sleep Otaku.init_wait_time
|
27
28
|
end
|
28
29
|
|
@@ -45,7 +46,7 @@ module Otaku
|
|
45
46
|
|
46
47
|
def process_data(data)
|
47
48
|
begin
|
48
|
-
Server.handler
|
49
|
+
Server.handler.process(data)
|
49
50
|
rescue
|
50
51
|
error = DataProcessError.new($!.inspect)
|
51
52
|
log(error.inspect)
|
data/otaku.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{otaku}
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["NgTzeYang"]
|
12
|
-
s.date = %q{2010-07-
|
12
|
+
s.date = %q{2010-07-21}
|
13
13
|
s.description = %q{}
|
14
14
|
s.email = %q{ngty77@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
data/spec/handler_spec.rb
CHANGED
@@ -31,7 +31,7 @@ describe "Otaku Service Handler" do
|
|
31
31
|
|
32
32
|
describe '>> initializing proc' do
|
33
33
|
|
34
|
-
expected = "
|
34
|
+
expected = "lambda { |watever| [\"a\", \"b\"].map { |x| puts(x) } }"
|
35
35
|
|
36
36
|
{
|
37
37
|
# ////////////////////////////////////////////////////////////////////////
|
@@ -59,7 +59,7 @@ describe "Otaku Service Handler" do
|
|
59
59
|
end
|
60
60
|
),
|
61
61
|
__LINE__ => (
|
62
|
-
|
62
|
+
lambda { |watever|
|
63
63
|
%w{a b}.map{|x|
|
64
64
|
puts x
|
65
65
|
}
|
@@ -98,7 +98,7 @@ describe "Otaku Service Handler" do
|
|
98
98
|
end
|
99
99
|
),
|
100
100
|
__LINE__ => (
|
101
|
-
|
101
|
+
lambda { |watever|
|
102
102
|
%w{a b}.map{|x| puts x }
|
103
103
|
}
|
104
104
|
),
|
@@ -125,7 +125,7 @@ describe "Otaku Service Handler" do
|
|
125
125
|
proc do |watever| %w{a b}.map do |x| puts x end end
|
126
126
|
),
|
127
127
|
__LINE__ => (
|
128
|
-
|
128
|
+
lambda { |watever| %w{a b}.map{|x| puts x } }
|
129
129
|
),
|
130
130
|
__LINE__ => (
|
131
131
|
Proc.new do |watever| %w{a b}.map do |x| puts x end end
|
@@ -213,14 +213,32 @@ describe "Otaku Service Handler" do
|
|
213
213
|
Otaku.start { |watever| %w{a b}.map { |x| puts x } }.proc.should.equal(expected)
|
214
214
|
end
|
215
215
|
|
216
|
-
should "
|
216
|
+
should "leave __FILE__ as __FILE__ [##{__LINE__}]" do
|
217
217
|
Otaku.start { |watever| __FILE__ }.proc.should.
|
218
|
-
equal("
|
218
|
+
equal("lambda { |watever| __FILE__ }" % File.expand_path('spec/handler_spec.rb'))
|
219
219
|
end
|
220
220
|
|
221
|
-
should "
|
221
|
+
should "leave __LINE__ as __LINE__ [##{__LINE__}]" do
|
222
222
|
Otaku.start { |watever| __LINE__ }.proc.should.
|
223
|
-
equal("
|
223
|
+
equal("lambda { |watever| __LINE__ }")
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
describe '>> fetching root' do
|
229
|
+
should 'return directory of current file' do
|
230
|
+
Otaku.start { |watever| __LINE__ }.root.should.equal(File.expand_path(File.dirname(__FILE__)))
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
describe '>> processing specified data' do
|
235
|
+
|
236
|
+
should 'reflect __FILE__ captured when the proc was 1st defined' do
|
237
|
+
Otaku.start{ |watever| __FILE__ }.process(:fake_data).should.equal(File.expand_path(__FILE__))
|
238
|
+
end
|
239
|
+
|
240
|
+
should 'reflect __LINE__ captured when the proc was 1st defined' do
|
241
|
+
Otaku.start{ |watever| __LINE__ }.process(:fake_data).should.equal(__LINE__)
|
224
242
|
end
|
225
243
|
|
226
244
|
end
|
data/spec/integration_spec.rb
CHANGED
@@ -42,9 +42,19 @@ describe "Otaku Service" do
|
|
42
42
|
Otaku.process(:watever_data).should.equal(File.expand_path(__FILE__))
|
43
43
|
end
|
44
44
|
|
45
|
-
should '
|
45
|
+
should 'reflect __LINE__ as captured when declaring proc' do
|
46
46
|
Otaku.start{|data| __LINE__ }
|
47
|
-
Otaku.process(:watever_data).should.
|
47
|
+
Otaku.process(:watever_data).should.equal(__LINE__.pred)
|
48
|
+
end
|
49
|
+
|
50
|
+
should 'have $LOAD_PATH include Otaku.root' do
|
51
|
+
Otaku.start{|data| $LOAD_PATH }
|
52
|
+
Otaku.process(:watever_data).should.include(Otaku.root)
|
53
|
+
end
|
54
|
+
|
55
|
+
should 'have $LOAD_PATH include Otaku::Server#handler.root' do
|
56
|
+
Otaku.start{|data| $LOAD_PATH }
|
57
|
+
Otaku.process(:watever_data).should.include(Otaku::Server.handler.root)
|
48
58
|
end
|
49
59
|
|
50
60
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: otaku
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 2
|
10
|
+
version: 0.2.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- NgTzeYang
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-07-
|
18
|
+
date: 2010-07-21 00:00:00 +08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|