rserve-client 0.1.9 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
@@ -1,5 +1,13 @@
1
- === 0.1.9 / 2010-06-04
1
+ === 0.2.0 / 2010-06-15
2
+ * Session implemented.
3
+ * Retrieve auth information from server first responde. TODO: Implement authentification
4
+ * Rserve::Protocol get_int and get_long uses pack. Spec for test compatibility for old method
5
+ * Added benchmark, comparing Rserve with RinRuby and RsRuby
6
+ * Windows Support:
7
+ * On windows, any new connection closes the previous. Rserve on Windows can't process parallel connections
8
+ * All Specification works on Windows
2
9
 
10
+ === 0.1.9 / 2010-06-04
3
11
  * Documentation:
4
12
  * Added commentaries on examples/regression.txt
5
13
  * Examples.txt on main directory renamed to Introduction.txt
@@ -4,6 +4,10 @@ Introduction.txt
4
4
  Manifest.txt
5
5
  README.txt
6
6
  Rakefile
7
+ benchmark/benchmark.rb
8
+ benchmark/comparison_2010_06_07.xls
9
+ benchmark/comparison_2010_06_07_using_pack.xls
10
+ benchmark/plot.rb
7
11
  data/gettysburg.txt
8
12
  examples/gettysburg.rb
9
13
  examples/hello_world.rb
@@ -36,9 +40,11 @@ lib/rserve/rexp/vector.rb
36
40
  lib/rserve/rexp/wrapper.rb
37
41
  lib/rserve/rfactor.rb
38
42
  lib/rserve/rlist.rb
43
+ lib/rserve/session.rb
39
44
  lib/rserve/talk.rb
40
45
  lib/rserve/withattributes.rb
41
46
  lib/rserve/withnames.rb
47
+ spec/rserve_connection_on_unix_spec.rb
42
48
  spec/rserve_connection_spec.rb
43
49
  spec/rserve_double_spec.rb
44
50
  spec/rserve_genericvector_spec.rb
@@ -52,6 +58,7 @@ spec/rserve_rexp_wrapper_spec.rb
52
58
  spec/rserve_rexpfactory_spec.rb
53
59
  spec/rserve_rfactor_spec.rb
54
60
  spec/rserve_rlist_spec.rb
61
+ spec/rserve_session_spec.rb
55
62
  spec/rserve_spec.rb
56
63
  spec/rserve_talk_spec.rb
57
64
  spec/rserve_withnames_spec.rb
data/README.txt CHANGED
@@ -16,10 +16,11 @@ Follows closely the new Java client API, but maintains all Ruby conventions when
16
16
  * Requires Rserve installed on the server machine. On debian / ubuntu, you should use <tt>sudo apt-get install r-cran-rserve</tt>
17
17
  Pros:
18
18
  * Work with Ruby 1.8, 1.9 and JRuby 1.5.
19
- * Should work on Windows (not tested yet)
20
- * Implements almost completely R's datatypes: integer, doubles, chars, logical vectors, lists and raw data.
21
- * Follows closely the Java API, so any change on the server API could be adopted without much problem
22
- * Fast
19
+ * Work on Windows. Rserve limitations on that plataform applies (single connection, crash on parse errors)
20
+ * Retrieve and assign various R's datatypes: integer, doubles, chars, logical vectors, lists and raw data.
21
+ * Session allows to process data asynchronously. You start a command, detach the process and retrieve result later. You can marshall the session, store on file or database and use it when you need it.
22
+ * Ruby API follows closely the Java API, so any change on the server API could be adopted without much problem
23
+ * Fast: 5-10 times faster than RinRuby.
23
24
  * Easy management of differences between R and Ruby, or "You can have your cake and eat it, too!"
24
25
  * From R side: The evaluation of expression retrieves REXP object, with a lot of information from original variables on R. You can construct your REXP objects and <tt>assign</tt> them to variables on R fast using binary TCP/IP port or send complex expression without lost of time using <tt>void_eval</tt>
25
26
  * Between R and Ruby: Every REXP object implements methods to convert to specific Ruby type: as_integers, as_doubles, as_strings
@@ -38,16 +39,17 @@ Cons:
38
39
  * Work with Ruby 1.8, 1.9 and JRuby 1.5
39
40
  * All API tested
40
41
  * Cons:
41
- * VERY SLOW
42
+ * VERY SLOW on assignation
42
43
  * Very limited datatypes: Only vector and Matrix
43
44
  * RSRuby
44
45
  * C Extension for Ruby, linked to R's shared library
45
46
  * Pros:
46
- * Very fast data access
47
+ * Blazing speed! 5-10 times faster than Rserve and 100-1000 than RinRuby.
47
48
  * Seamless integration with ruby. Every method and object is treated like a Ruby one
48
49
  * Cons:
49
50
  * Transformation between R and Ruby types aren't trivial
50
51
  * Dependent on operating system, Ruby implementation and R version
52
+ * Ocassionaly crash
51
53
  * Not available for alternative implementations of Ruby (JRuby, IronRuby and Rubinius)
52
54
 
53
55
 
@@ -55,7 +57,6 @@ Cons:
55
57
 
56
58
  Implements
57
59
 
58
- * Sessions
59
60
  * Authentification
60
61
  * Original test
61
62
 
@@ -0,0 +1,113 @@
1
+ # Compares rserve, rinruby and rsruby
2
+ # in retrieval and assign of information
3
+ $:.unshift(File.dirname(__FILE__)+"/../lib")
4
+
5
+ require 'rubygems'
6
+ require 'rserve'
7
+ require 'rinruby'
8
+ begin
9
+ require 'rsruby'
10
+ rs=RSRuby.instance
11
+ rescue LoadError
12
+ rs=nil
13
+ end
14
+ require 'benchmark'
15
+ data_size=30000
16
+ tries=50
17
+ con=Rserve::Connection.new
18
+ R.eval("1",false)
19
+ data=data_size.times.map {rand()}
20
+ data_integer=data_size.times.map {rand(100)}
21
+ Benchmark.bm(30) do |x|
22
+ x.report("assign '1' rinruby") {
23
+ tries.times {
24
+ R.a=1
25
+ }
26
+ }
27
+ x.report("assign '1' rserve") {
28
+ con.assign("a", 1)
29
+ }
30
+ if rs
31
+ x.report("assign '1' rsruby") {
32
+ rs.assign('a',1)
33
+ }
34
+ end
35
+ x.report("assign double(#{data_size}) rinruby") {
36
+ tries.times {
37
+ R.a=data
38
+ }
39
+ }
40
+ x.report("assign double(#{data_size}) rserve") {
41
+ con.assign("a", data)
42
+ }
43
+ if rs
44
+ x.report("assign double(#{data_size}) rsruby") {
45
+ rs.assign("a", data)
46
+ }
47
+ end
48
+ x.report("void_eval rinruby") {
49
+ tries.times {
50
+ R.eval("1",false)
51
+ }
52
+ }
53
+ x.report("void_eval rserve") {
54
+ tries.times {
55
+ con.void_eval("1")
56
+ }
57
+ }
58
+ if rs
59
+ x.report("void_eval rsruby") {
60
+ tries.times {
61
+ rs.eval("1")
62
+ }
63
+ }
64
+ end
65
+ # Assign data
66
+ R.a=1
67
+ con.assign('a',1)
68
+ if rs
69
+ rs.assign('a',1)
70
+ end
71
+ x.report("get '1' rinruby") {
72
+ tries.times {
73
+ R.pull('a')
74
+ }
75
+ }
76
+ x.report("get '1' rserve") {
77
+ tries.times {
78
+ con.eval('a').to_ruby
79
+ }
80
+ }
81
+ if rs
82
+ x.report("get '1' rsruby") {
83
+ tries.times {
84
+ rs.a
85
+ }
86
+ }
87
+ end
88
+
89
+ R.a=data
90
+ con.assign('a',data)
91
+ if rs
92
+ rs.assign('a',data)
93
+ end
94
+ x.report("get double(#{data_size}) rinruby") {
95
+ tries.times {
96
+ R.pull('a')
97
+ }
98
+ }
99
+ x.report("get double(#{data_size}) rserve") {
100
+ tries.times {
101
+ con.eval('a').to_ruby
102
+ }
103
+ }
104
+
105
+ if rs
106
+ x.report("get double(#{data_size}) rsruby") {
107
+ tries.times {
108
+ rs.a
109
+ }
110
+ }
111
+ end
112
+
113
+ end
@@ -0,0 +1,69 @@
1
+ # Creates a graph with multiple size assignment and retrieval
2
+
3
+ require 'rubygems'
4
+ require 'rserve'
5
+ require 'rinruby'
6
+ require 'benchmark'
7
+ require 'statsample'
8
+ require 'rsruby'
9
+
10
+ max=45
11
+ R.eval("1")
12
+ rs=RSRuby.instance
13
+ con=Rserve::Connection.new
14
+ rserve_assign = []
15
+ rserve_retrieve = []
16
+ rinruby_assign = []
17
+ rinruby_retrieve = []
18
+ rs_assign=[]
19
+ rs_retrieve=[]
20
+
21
+ max.times.map {|x|
22
+ puts "Rserve #{x}"
23
+ start=Time.new.to_f
24
+ con.assign('a',(x*100+1).times.map {rand})
25
+ a=Time.new.to_f-start
26
+
27
+ start=Time.new.to_f
28
+
29
+ con.eval('a').to_f
30
+
31
+ b=Time.new.to_f-start
32
+
33
+ rserve_assign.push(a)
34
+ rserve_retrieve.push(b)
35
+ }
36
+ max.times.map {|x|
37
+
38
+ puts "Rinruby #{x}"
39
+ start=Time.new.to_f
40
+ R.assign("a", (x*100+1).times.map {rand})
41
+ a=Time.new.to_f-start
42
+ start=Time.new.to_f
43
+ R.pull('a')
44
+ b=Time.new.to_f-start
45
+ rinruby_assign.push(a)
46
+ rinruby_retrieve.push(b)
47
+ }
48
+
49
+
50
+ max.times.map {|x|
51
+ puts "RsRuby #{x}"
52
+ start=Time.new.to_f
53
+ rs.assign('a',(x*100+1).times.map {rand})
54
+ a=Time.new.to_f-start
55
+
56
+ start=Time.new.to_f
57
+
58
+ rs.a.to_f
59
+
60
+ b=Time.new.to_f-start
61
+
62
+ rs_assign.push(a)
63
+ rs_retrieve.push(b)
64
+ }
65
+
66
+
67
+ ds_assign={'times'=>(1..max).map {|v| v*100+1}.to_scale,'rserve assign'=> rserve_assign.to_scale, 'rserve retrieve'=>rserve_retrieve.to_scale, 'rinruby assign'=>rinruby_assign.to_scale, 'rinruby retrieve'=>rinruby_retrieve.to_scale, 'rs_assign'=>rs_assign.to_scale, 'rs_retrieve'=>rs_retrieve.to_scale}.to_dataset
68
+ ds_assign.fields=['times','rs_assign','rserve_assign','rinruby_assign','rs_retrieve','rserve_retrieve','rinruby_retrieve']
69
+ Statsample::Excel.write(ds_assign,'comparison.xls')
@@ -5,4 +5,4 @@ x = c.eval("R.version.string");
5
5
  puts x.as_string
6
6
 
7
7
 
8
- d = c.eval("rnorm(100)").as_doubles
8
+ d = c.eval("rnorm(10000)").as_doubles
@@ -1,7 +1,7 @@
1
1
  require 'socket'
2
2
 
3
3
  module Rserve
4
- VERSION = '0.1.9'
4
+ VERSION = '0.2.0'
5
5
  end
6
6
 
7
7
 
@@ -14,6 +14,7 @@ require 'rserve/packet'
14
14
  require 'rserve/talk'
15
15
  require 'rserve/rexp'
16
16
  require 'rserve/engine'
17
+ require 'rserve/session'
17
18
  require 'rserve/connection'
18
19
  require 'rserve/rlist'
19
20
  require 'rserve/rfactor'
@@ -1,5 +1,7 @@
1
+ require 'rbconfig'
1
2
  module Rserve
2
3
  class Connection < Rserve::Engine
4
+ @@connected_object=nil
3
5
  include Rserve::Protocol
4
6
 
5
7
  # :section: Exceptions
@@ -27,6 +29,7 @@ module Rserve
27
29
  attr_reader :rt
28
30
  attr_reader :s
29
31
  attr_reader :port
32
+ attr_reader :session
30
33
  attr_writer :transfer_charset
31
34
  attr_reader :rsrv_version
32
35
  attr_writer :persistent
@@ -40,10 +43,13 @@ module Rserve
40
43
  @hostname = opts.delete(:hostname) || "127.0.0.1"
41
44
  @port_number = opts.delete(:port_number) || 6311
42
45
  @max_tries = opts.delete(:max_tries) || 5
46
+ @session = opts.delete(:session) || nil
43
47
  @tries = 0
44
48
  @connected=false
45
-
46
-
49
+ if (!@session.nil?)
50
+ @hostname=@session.host
51
+ @port_number=@session.port
52
+ end
47
53
  begin
48
54
  #puts "Tryin to connect..."
49
55
  connect
@@ -72,22 +78,49 @@ module Rserve
72
78
  end
73
79
  end
74
80
  def connect
75
-
81
+ # On windows, Rserve doesn't allows concurrent connections.
82
+ # So, we must close the last open connection first
83
+ if RbConfig::CONFIG['arch']=~/mswin/ and !@@connected_object.nil?
84
+ @@connected_object.close
85
+ end
86
+
76
87
  close if @connected
88
+
77
89
  @s = TCPSocket::new(@hostname, @port_number)
78
90
  @rt=Rserve::Talk.new(@s)
79
- #puts "Connected"
80
- # Accept first input
81
- input=@s.recv(32).unpack("a4a4a4a20")
82
- raise IncorrectServer,"Handshake failed: Rsrv signature expected, but received [#{input[0]}]" unless input[0]=="Rsrv"
83
- @rsrv_version=input[1].to_i
84
- raise IncorrectServerVersion, "Handshake failed: The server uses more recent protocol than this client." if @rsrv_version>103
85
- @protocol=input[2]
86
- raise IncorrectProtocol, "Handshake failed: unsupported transfer protocol #{@protocol}, I talk only QAP1." if @protocol!="QAP1"
87
- @extra=input[4]
91
+ if @session.nil?
92
+ #puts "Connected"
93
+ # Accept first input
94
+ input=@s.recv(32).unpack("a4a4a4a4a4a4a4a4")
95
+ raise IncorrectServer,"Handshake failed: Rsrv signature expected, but received [#{input[0]}]" unless input[0]=="Rsrv"
96
+ @rsrv_version=input[1].to_i
97
+ raise IncorrectServerVersion, "Handshake failed: The server uses more recent protocol than this client." if @rsrv_version>103
98
+ @protocol=input[2]
99
+ raise IncorrectProtocol, "Handshake failed: unsupported transfer protocol #{@protocol}, I talk only QAP1." if @protocol!="QAP1"
100
+ (3..7).each do |i|
101
+ attr=input[i]
102
+ if (attr=="ARpt")
103
+ if (!auth_req) # this method is only fallback when no other was specified
104
+ auth_req=true
105
+ auth_type=AT_plain
106
+ end
107
+ end
108
+ if (attr=="ARuc")
109
+ auth_req=true
110
+ authType=AT_crypt
111
+ end
112
+ if (attr[0]=='K')
113
+ key=attr[1,3]
114
+ end
115
+
116
+ end
117
+ else # we have a session to take care of
118
+ @s.write(@session.key.pack("C*"))
119
+ @rsrv_version=session.rsrv_version
120
+ end
88
121
  @connected=true
122
+ @@connected_object=self
89
123
  @last_error="OK"
90
-
91
124
  end
92
125
  def connected?
93
126
  @connected
@@ -99,6 +132,7 @@ module Rserve
99
132
  end
100
133
  raise "Can't close socket" unless @s.closed?
101
134
  @connected=false
135
+ @@connected_object=nil
102
136
  true
103
137
  end
104
138
  def get_server_version
@@ -119,6 +153,20 @@ module Rserve
119
153
  end
120
154
 
121
155
 
156
+ def void_eval_detach(cmd)
157
+ raise NotConnected if !connected? or rt.nil?
158
+ rp=rt.request(:cmd=>Rserve::Protocol::CMD_detachedVoidEval,:cont=>cmd+"\n")
159
+ if rp.nil? or !rp.ok?
160
+ raise EvalError.new(rp), "detached void eval failed : #{rp.to_s}"
161
+ else
162
+ s=Rserve::Session.new(self,rp)
163
+ close
164
+ s
165
+ end
166
+ end
167
+
168
+
169
+
122
170
  # evaluates the given command and retrieves the result
123
171
  # * @param cmd command/expression string
124
172
  # * @return R-xpression or <code>null</code> if an error occured */
@@ -233,6 +281,19 @@ module Rserve
233
281
  raise "Shutdown failed"
234
282
  end
235
283
  end
236
-
284
+ # detaches the session and closes the connection (requires Rserve 0.4+).
285
+ # The session can be only resumed by calling RSession.attach
286
+
287
+ def detach
288
+ raise NotConnected if !connected? or rt.nil?
289
+ rp=rt.request(:cmd=>Rserve::Protocol::CMD_detachSession)
290
+ if !rp.nil? and rp.ok?
291
+ s=Rserve::Session.new(self,rp)
292
+ close
293
+ s
294
+ else
295
+ raise "Cannot detach"
296
+ end
297
+ end
237
298
  end
238
299
  end
@@ -1,3 +1,4 @@
1
+ require 'rbconfig'
1
2
  module Rserve
2
3
  #
3
4
  # This module encapsulates methods and constants related to QAP1 protocol used by Rserv. Follows almost exactly the interface on RTalk class
@@ -7,6 +8,15 @@ module Rserve
7
8
  # Policy: No other class should know about the internal of protocol!
8
9
  # See Rtalk class on Java version.
9
10
  module Protocol
11
+ # Arch dependent Long Nil value
12
+ case Config::CONFIG['arch']
13
+ when 'i686-linux'
14
+ LONG_NA=9221120237041092514 # :nodoc:
15
+ when /mswin/
16
+ LONG_NA=9221120237041092514 # :nodoc:
17
+ else
18
+ LONG_NA=9218868437227407266 # :nodoc:
19
+ end
10
20
  # Defines from Rsrv.h
11
21
  CMD_RESP=0x010000 # all responses have this flag set
12
22
  RESP_OK=(CMD_RESP|0x0001) # command succeeded; returned parameters depend on the command issued
@@ -162,7 +172,9 @@ module Rserve
162
172
  # make sure that the buffer is big enough
163
173
 
164
174
  def get_int(buf, o)
165
- #return buf.slice(o,4).pack("C*").unpack("l")[0]
175
+ buf[o,4].pack("C*").unpack("l")[0]
176
+ end
177
+ def get_int_original(buf,o) # :nodoc:
166
178
  v=((buf[o]&255)|((buf[o+1]&255)<<8)|((buf[o+2]&255)<<16)|((buf[o+3]&255)<<24))
167
179
  v >= MAX_LONG_SIGNED ? v-MAX_LONG_UNSIGNED : v
168
180
  end
@@ -187,12 +199,20 @@ module Rserve
187
199
  # @param o offset (8 bytes will be used)
188
200
  # @return long value */
189
201
  def get_long(buf, o)
202
+ buf[o,8].pack("CCCCCCCC").unpack("Q")[0]
203
+ end
204
+ def get_long_original(buf,o) #:nodoc:
190
205
  low=(get_int(buf,o))&0xffffffff;
191
206
  hi=(get_int(buf,o+4))&0xffffffff;
192
207
  hi<<=32; hi|=low;
193
208
  hi
194
209
  end
210
+
195
211
  def longBitsToDouble(bits)
212
+ (bits==LONG_NA) ? Rserve::REXP::Double::NA : [bits].pack("Q").unpack("d")[0]
213
+ end
214
+ # Complete version of longBitsToDouble, as Java documentation established
215
+ def longBitsToDouble_old(bits) # :nodoc:
196
216
  s = ((bits >> 63) == 0) ? 1 : -1;
197
217
  e = ((bits >> 52) & 0x7ff)
198
218
  m = (e == 0) ?
@@ -200,6 +220,7 @@ module Rserve
200
220
  (bits & 0xfffffffffffff) | 0x10000000000000;
201
221
  s*m*2**(e-1075)
202
222
  end
223
+
203
224
  def doubleToRawLongBits(double)
204
225
  [double].pack("d").unpack("Q")[0]
205
226
  end
@@ -1,8 +1,8 @@
1
1
  module Rserve
2
- # Basic class representing an object of any type in R. Each type in R in represented by a specific subclass.
3
- #
4
- # This class defines basic accessor methods (<tt>as</tt><i>XXX</i>), type check methods (<tt>is</tt><i>XXX</i>), gives access to attributes ({@link #getAttribute}, {@link #hasAttribute}) as well as several convenience methods. If a given method is not applicable to a particular type, it will throw the {@link MismatchException} exception.
2
+ # Basic class representing an object of any type in R. Each type in R in represented by a specific subclass.
5
3
  #
4
+ # This class defines basic accessor methods (<tt>as</tt>_<i>xxx</i>), type check methods (<i>XXX</i><tt>?</tt>), gives access to attributes (REXP.get_attribute, REXP.has_attribute?) as well as several convenience methods. If a given method is not applicable to a particular type, it will throw the MismatchException exception.
5
+ #
6
6
  # This root class will throw on any accessor call and returns <code>false</code> for all type methods. This allows subclasses to override accessor and type methods selectively.
7
7
  #
8
8
  class REXP
@@ -16,181 +16,232 @@ module Rserve
16
16
  # specifies how many items of a vector or list will be displayed in {@link #toDebugString}
17
17
  MaxDebugItems = 32
18
18
  # :section: type checks
19
- # check whether the <code>REXP</code> object is a character vector (string)
20
- # @return <code>true</code> if the receiver is a character vector, <code>false</code> otherwise
21
-
19
+
20
+ # check whether the <code>REXP</code> object is a character vector (string).
21
+ #
22
+ # @return [boolean] <code>true</code> if the receiver is a character vector, <code>false</code> otherwise
22
23
  def string?
23
24
  false
24
25
  end
25
26
 
26
- # # check whether the <code>REXP</code> object is a numeric vector
27
- # @return <code>true</code> if the receiver is a numeric vector, <code>false</code> otherwise
27
+ # check whether the <code>REXP</code> object is a numeric vector.
28
+ #
29
+ # @return [boolean] <code>true</code> if the receiver is a numeric vector, <code>false</code> otherwise
28
30
 
29
31
  def numeric?
30
32
  false
31
33
  end
32
- # check whether the <code>REXP</code> object is an integer vector
33
- # @return <code>true</code> if the receiver is an integer vector, <code>false</code> otherwise
34
+ # check whether the <code>REXP</code> object is an integer vector.
35
+ #
36
+ # @return [boolean] <code>true</code> if the receiver is an integer vector, <code>false</code> otherwise
34
37
  def integer?
35
38
  false
36
39
  end
37
- # check whether the <code>REXP</code> object is NULL
38
- # @return <code>true</code> if the receiver is NULL, <code>false</code> otherwise
40
+ # check whether the <code>REXP</code> object is NULL.
41
+ #
42
+ # @return [boolean] <code>true</code> if the receiver is NULL, <code>false</code> otherwise
39
43
  def null?
40
44
  false
41
45
  end
42
- # check whether the <code>REXP</code> object is a factor
43
- # @return <code>true</code> if the receiver is a factor, <code>false</code> otherwise
46
+
47
+ # check whether the <code>REXP</code> object is a factor.
48
+ #
49
+ # @return [boolean] <code>true</code> if the receiver is a factor, <code>false</code> otherwise
44
50
  def factor?
45
51
  false
46
52
  end
47
- # check whether the <code>REXP</code> object is a list (either generic vector or a pairlist - i.e. {@link #asList()} will succeed)
48
- # @return <code>true</code> if the receiver is a generic vector or a pair-list, <code>false</code> otherwise
53
+
54
+ # check whether the <code>REXP</code> object is a list (either generic vector or a pairlist - i.e. REXP.asList() will succeed).
55
+ #
56
+ # @return [boolean] <code>true</code> if the receiver is a generic vector or a pair-list, <code>false</code> otherwise
49
57
  def list?
50
58
  false
51
59
  end
52
- # check whether the <code>REXP</code> object is a pair-list
53
- # @return <code>true</code> if the receiver is a pair-list, <code>false</code> otherwise
60
+ # check whether the <code>REXP</code> object is a pair-list.
61
+ #
62
+ # @return [boolean] <code>true</code> if the receiver is a pair-list, <code>false</code> otherwise
54
63
  def pair_list?
55
64
  false
56
65
  end
57
- # check whether the <code>REXP</code> object is a logical vector
58
- # @return <code>true</code> if the receiver is a logical vector, <code>false</code> otherwise */
66
+ # check whether the <code>REXP</code> object is a logical vector.
67
+ #
68
+ # @return [boolean] <code>true</code> if the receiver is a logical vector, <code>false</code> otherwise */
59
69
  def logical?
60
70
  false
61
71
  end
62
- # check whether the <code>REXP</code> object is an environment
63
- # @return <code>true</code> if the receiver is an environment, <code>false</code> otherwise
72
+ # check whether the <code>REXP</code> object is an environment.
73
+ #
74
+ # @return [boolean] <code>true</code> if the receiver is an environment, <code>false</code> otherwise
64
75
  def environment?
65
76
  false
66
77
  end
67
- # check whether the <code>REXP</code> object is a language object
68
- # @return <code>true</code> if the receiver is a language object, <code>false</code> otherwise
78
+ # check whether the <code>REXP</code> object is a language object.
79
+ #
80
+ # @return [boolean] <code>true</code> if the receiver is a language object, <code>false</code> otherwise
69
81
  def language?
70
82
  false
71
83
  end
72
- # check whether the <code>REXP</code> object is an expression vector
73
- # @return <code>true</code> if the receiver is an expression vector, <code>false</code> otherwise
84
+ # check whether the <code>REXP</code> object is an expression vector.
85
+ #
86
+ # @return [boolean] <code>true</code> if the receiver is an expression vector, <code>false</code> otherwise
74
87
  def expression?
75
88
  false
76
89
  end
77
- # check whether the <code>REXP</code> object is a symbol
78
- # @return <code>true</code> if the receiver is a symbol, <code>false</code> otherwise
90
+ # check whether the <code>REXP</code> object is a symbol.
91
+ #
92
+ # @return [boolean] <code>true</code> if the receiver is a symbol, <code>false</code> otherwise
79
93
  def symbol?
80
94
  false
81
95
  end
82
- # check whether the <code>REXP</code> object is a vector
83
- # @return <code>true</code> if the receiver is a vector, <code>false</code> otherwise
96
+ # check whether the <code>REXP</code> object is a vector.
97
+ #
98
+ # @return [boolean] <code>true</code> if the receiver is a vector, <code>false</code> otherwise
84
99
  def vector?
85
100
  false
86
101
  end
87
102
  # check whether the <code>REXP</code> object is a raw vector
88
- # @return <code>true</code> if the receiver is a raw vector, <code>false</code> otherwise
103
+ # @return [boolean] <code>true</code> if the receiver is a raw vector, <code>false</code> otherwise
89
104
  def raw?
90
105
  false
91
106
  end
92
107
  # check whether the <code>REXP</code> object is a complex vector
93
- # @return <code>true</code> if the receiver is a complex vector, <code>false</code> otherwise
108
+ # @return [boolean] <code>true</code> if the receiver is a complex vector, <code>false</code> otherwise
94
109
  def complex?
95
110
  false
96
111
  end
97
112
  # check whether the <code>REXP</code> object is a recursive obejct
98
- # @return <code>true</code> if the receiver is a recursive object, <code>false</code> otherwise
113
+ # @return [boolean] <code>true</code> if the receiver is a recursive object, <code>false</code> otherwise
99
114
  def recursive?
100
115
  false
101
116
  end
102
117
  # check whether the <code>REXP</code> object is a reference to an R object
103
- # @return <code>true</code> if the receiver is a reference, <code>false</code> otherwise
118
+ # @return [boolean] <code>true</code> if the receiver is a reference, <code>false</code> otherwise
104
119
  def reference?
105
120
  false
106
121
  end
107
122
 
108
123
  # :section: basic accessor methods
109
- # returns the contents as an array of Strings (if supported by the represented object)
124
+
125
+ # returns the contents as an array of Strings (if supported by the represented object).
126
+ #
127
+ # @return [Array]
110
128
  def as_strings
111
129
  raise MismatchException, "String"
112
130
  end
113
131
  # returns the contents as an array of integers (if supported by the represented object)
132
+ #
133
+ # @return [Array]
114
134
 
115
135
  def as_integers
116
136
  raise MismatchException, "int"
117
137
  end
118
138
 
119
- # returns the contents as an array of doubles (if supported by the represented object)
139
+ # returns the contents as an array of floats (C double precision) (if supported by the represented object).
140
+ #
141
+ # @return [Array]
142
+
120
143
  def as_doubles
121
144
  raise MismatchException,"double"
122
145
  end
123
146
 
124
- # On Ruby, Float are stored in double precision
147
+ # On Ruby, Float are stored in double precision.
148
+ #
149
+ # @return [Array]
125
150
  def as_floats
126
151
  as_doubles
127
152
  end
128
153
 
129
- # returns the contents as an array of bytes (if supported by the represented object)
154
+ # returns the contents as an array of bytes (if supported by the represented object).
155
+ #
156
+ # @return [Array]
157
+
130
158
  def as_bytes
131
159
  raise MismatchException , "byte"
132
160
  end
133
161
  # returns the contents as a (named) list (if supported by the represented object)
162
+ #
163
+ # @return [Array]
134
164
  def as_list
135
165
  raise MismatchException,"list"
136
166
  end
137
- # returns the contents as a factor (if supported by the represented object)
167
+ # returns the contents as a factor (if supported by the represented object).
168
+ #
169
+ # @return [RFactor]
138
170
  def as_factor
139
171
  raise MismatchException,"factor"
140
172
  end
141
173
 
142
- # returns the length of a vector object. Note that we use R semantics here, i.e. a matrix will have a length of <i>m * n</i> since it is represented by a single vector (see {@link #dim} for retrieving matrix and multidimentional-array dimensions).
143
- # * @return length (number of elements) in a vector object
144
- # * @throws MismatchException if this is not a vector object
174
+ # returns the length of a vector object. Note that we use R semantics here, i.e. a matrix will have a length of <i>m * n</i> since it is represented by a single vector (see REXP.dim) for retrieving matrix and multidimentional-array dimensions).
175
+ #
176
+ # @return [Integer] length (number of elements) in a vector object.
145
177
  def length
146
178
  raise MismatchException, "vector"
147
179
  end
148
180
 
149
- # returns a boolean vector of the same length as this vector with <code>true</code> for NA values and <code>false</code> for any other values
150
- # * @return a boolean vector of the same length as this vector with <code>true</code> for NA values and <code>false</code> for any other values
151
- # * @throws MismatchException if this is not a vector object
181
+ # returns a boolean vector of the same length as this vector with <code>true</code> for NA values and <code>false</code> for any other values.
182
+ #
183
+ # @return [boolean] a boolean vector of the same length as this vector with <code>true</code> for NA values and <code>false</code> for any other values.
184
+ #
152
185
  def na?
153
186
  raise MismatchException, "vector"
154
187
  end
155
188
 
156
189
  # :section: convenience accessor methods
190
+
191
+
157
192
  # convenience method corresponding to <code>as_integer()[0]</code>
158
- # @return first entry returned by {@link #as_integer}
193
+ #
194
+ # @return [Integer] first entry returned by as_integers()
159
195
  def as_integer
160
196
  as_integers[0]
161
197
  end
198
+ # Alias for as_integer().
199
+ #
200
+ # @return [Integer]
201
+
162
202
  def to_i
163
203
  as_integers[0]
164
204
  end
165
- # convenience method corresponding to <code>asDoubles()[0]</code>
166
- # @return first entry returned by {@link #asDoubles}
205
+ # convenience method corresponding to <code>as_floats[0]</code>.
206
+ #
207
+ # @return [Float] first entry returned by as_doubles()
167
208
  def as_double
168
209
  as_doubles[0]
169
210
  end
211
+ # Alias for as_double()
212
+ #
213
+ # @return [Float]
170
214
  def as_float
171
215
  as_double
172
216
  end
217
+ # Alias for as_float()
218
+ #
219
+ # @return [Float]
173
220
  def to_f
174
221
  as_double
175
222
  end
176
- # convenience method corresponding to <code>asStrings()[0]</code>
177
- # @return first entry returned by {@link #asStrings}
223
+ # convenience method corresponding to <code>as_strings[0]</code>.
224
+ #
225
+ # @return [String] first entry returned by REXP.as_strings
178
226
  def as_string
179
227
  as_strings[0]
180
228
  end
181
- # // methods common to all REXPs
182
229
 
183
- # retrieve an attribute of the given name from this object
184
- # * @param name attribute name
185
- # * @return attribute value or <code>null</code> if the attribute does not exist
230
+ # :section: methods common to all REXPs
231
+
232
+ # Retrieve an attribute of the given name from this object.
233
+ #
234
+ # @param [String] attribute name.
235
+ # @return [Rlist, nil] attribute value or <code>nil</code> if the attribute does not exist
186
236
 
187
237
  def get_attribute(name)
188
238
  has_attribute?(name) ? @attr.as_list[name] : nil
189
239
  end
190
240
 
191
- # checks whether this obejct has a given attribute
192
- # * @param name attribute name
193
- # * @return <code>true</code> if the attribute exists, <code>false</code> otherwise
241
+ # checks whether this object has a given attribute.
242
+ #
243
+ # @param [String] attribute name.
244
+ # @return [boolean] <code>true</code> if the attribute exists, <code>false</code> otherwise
194
245
  def has_attribute? (name)
195
246
  !@attr.nil? and @attr.list? and !@attr.as_list[name].nil?
196
247
  end
@@ -198,8 +249,9 @@ module Rserve
198
249
 
199
250
  # :section: helper methods common to all REXPs
200
251
 
201
- # returns dimensions of the object (as determined by the "<code>dim</code>" attribute)
202
- # @return an array of integers with corresponding dimensions or <code>null</code> if the object has no dimension attribute
252
+ # Returns dimensions of the object (as determined by the REXP::dim() attribute).
253
+ #
254
+ # @return [Array] an array of integers with corresponding dimensions or <code>nil</code> if the object has no dimension attribute
203
255
  def dim
204
256
  begin
205
257
  return has_attribute?("dim") ? @attr.as_list['dim'].as_integers : nil;
@@ -209,9 +261,10 @@ module Rserve
209
261
  nil
210
262
  end
211
263
 
212
- # determines whether this object inherits from a given class in the same fashion as the <code>inherits()</code> function in R does (i.e. ignoring S4 inheritance)
213
- # @param klass class name
214
- # @return <code>true</code> if this object is of the class <code>klass</code>, <code>false</code> otherwise
264
+ # determines whether this object inherits from a given class in the same fashion as the <code>inherits()</code> function in R does (i.e. ignoring S4 inheritance).
265
+ #
266
+ # @param [String] klass class name.
267
+ # @return [boolean] <code>true</code> if this object is of the class <code>klass</code>, <code>false</code> otherwise.
215
268
  def inherits?(klass)
216
269
  return false if (!has_attribute? "class")
217
270
  begin
@@ -226,20 +279,23 @@ module Rserve
226
279
 
227
280
 
228
281
 
229
- # returns representation that it useful for debugging (e.g. it includes attributes and may include vector values -- see {@link #maxDebugItems})
230
- # @return extended description of the obejct -- it may include vector values
282
+ # returns representation that it useful for debugging (e.g. it includes attributes and may include vector values)
283
+ #
284
+ # @return [String] extended description of the obejct -- it may include vector values
231
285
  def to_debug_string
232
286
  (!@attr.nil?) ? (("<"+@attr.to_debug_string()+">")+to_s()) : to_s
233
287
  end
234
288
 
235
289
 
236
- #//======= complex convenience methods
290
+ # :section: complex convenience methods
291
+
292
+
237
293
  # returns the content of the REXP as a ruby matrix of doubles (2D-array: m[rows][cols]). You could use Matrix.rows(result) to create
238
294
  # a ruby matrix.
239
295
  # Matrix(c.eval("matrix(c(1,2,3,4,5,6),2,3)").as_double_matrix());</code>
240
296
  #
241
- # @return 2D array of doubles in the form double[rows][cols] or <code>null</code> if the contents is no 2-dimensional matrix of doubles
242
- def as_double_matrix()
297
+ # @return [Array] 2D array of doubles in the form double[rows][cols] or <code>nil</code> if the contents is no 2-dimensional matrix of doubles
298
+ def as_double_matrix
243
299
  ct = as_doubles()
244
300
  dim = get_attribute "dim"
245
301
  raise MismatchException, "matrix (dim attribute missing)" if dim.nil?
@@ -252,12 +308,16 @@ module Rserve
252
308
  # we need to copy everything, since we create 2d array from 1d array
253
309
  #r=m.times.map {|i| n.times.map {|j| ct[j*n+i]}}
254
310
  end
255
- # Returns a standard library's matrix
311
+ # Returns a standard library's matrix.
312
+ #
313
+ # @return [Matrix]
256
314
  def as_matrix
257
315
  require 'matrix'
258
316
  Matrix.rows(as_double_matrix)
259
317
  end
260
318
  # Returns the content of the REXP as a serie of nested arrays of X dimensions
319
+ #
320
+ # @return [Array]
261
321
  def as_nested_array
262
322
  ct=as_doubles
263
323
  dim = get_attribute "dim"
@@ -267,7 +327,7 @@ module Rserve
267
327
  split_array(ct,ds)
268
328
  end
269
329
 
270
- def split_array(ar, dims)
330
+ def split_array(ar, dims) # :nodoc:
271
331
  # puts "#{ar} - #{dims}"
272
332
  if dims.size==1
273
333
  raise "Improper size ar:#{ar} , dims=#{dims[0]}" if ar.size!=dims[0]
@@ -296,10 +356,10 @@ module Rserve
296
356
 
297
357
  # :section: tools
298
358
 
299
- # creates a data frame object from a list object using integer row names
300
- # * @param l a (named) list of vectors ({@link REXPVector} subclasses), each element corresponds to a column and all elements must have the same length
301
- # * @return a data frame object
302
- # * @throws MismatchException if the list is empty or any of the elements is not a vector
359
+ # creates a data frame object from a list object using integer row names.
360
+ #
361
+ # * @param [Rlist] a (named) list of vectors (REXP::Vector subclasses), each element corresponds to a column and all elements must have the same length.
362
+ # * @return [GenericVector] a data frame object representation.
303
363
  def self.create_data_frame(l)
304
364
  raise(MismatchException, "data frame (must have dim>0)") if l.nil? or l.size<1
305
365
  raise MismatchException, "data frame (contents must be vectors)" if (!(l[0].is_a? REXP::Vector))
@@ -321,7 +381,8 @@ module Rserve
321
381
  # If R object has attributes, the Ruby object is extended with Rserve::WithAttributes.
322
382
  # If R object is names, the Ruby object is extended with Rserve::WithNames and
323
383
  # their elements can be accessed with [] using numbers and literals.
324
- #
384
+ #
385
+ # @return [Object] Ruby object.
325
386
  def to_ruby
326
387
  #pp self
327
388
  v=to_ruby_internal
@@ -346,6 +407,9 @@ module Rserve
346
407
 
347
408
  v
348
409
  end
410
+ # Return the bare-bone representation of REXP as a Ruby Object.
411
+ # Called by REXP.to_ruby, so shouldn't be used directly by developers.
412
+ #
349
413
  def to_ruby_internal
350
414
  raise "You should implement to_ruby_internal for #{self.class}"
351
415
  end
@@ -7,6 +7,8 @@ module Rserve
7
7
  case Config::CONFIG['arch']
8
8
  when 'i686-linux'
9
9
  NA = 269653970229425383598692395468593241088322026492507901905402939417320933254485890939796955099302180188971623023005661539310855695935759376615857567599472873400528811349204333736152257830107446553333670133666606746438802800063353690283455789426038632208916715592554825644961573453826957827246636338344317943808
10
+ when /mswin/
11
+ NA = 269653970229425383598692395468593241088322026492507901905402939417320933254485890939796955099302180188971623023005661539310855695935759376615857567599472873400528811349204333736152257830107446553333670133666606746438802800063353690283455789426038632208916715592554825644961573453826957827246636338344317943808
10
12
  else
11
13
  NA = 0x100000000007a2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
12
14
  end
@@ -42,8 +44,13 @@ module Rserve
42
44
  end
43
45
 
44
46
  def na?(value=nil)
45
- return value == NA unless value.nil?
46
- @payload.map {|v| v==NA}
47
+ #if value.nil?
48
+ # @payload.map {|v| v.respond_to? :nan and v.nan?}
49
+ #else
50
+ # value.respond_to? :nan? and value.nan?
51
+ #end
52
+ return value.to_i == NA unless value.nil?
53
+ @payload.map {|v| v.to_i==NA}
47
54
  end
48
55
  def to_debug_string
49
56
  t=super
@@ -0,0 +1,29 @@
1
+ module Rserve
2
+ class Session
3
+ # serial version UID should only change if method signatures change
4
+ # significantly enough that previous versions cannot be used with
5
+ # current versions
6
+ include Rserve::Protocol
7
+ UID=-7048099825974875604
8
+ attr_reader :host
9
+ attr_reader :port
10
+ attr_reader :key
11
+ attr_reader :attach_packet
12
+ attr_reader :rsrv_version
13
+ def initialize(con,packet)
14
+ @host=con.hostname
15
+ @rsrv_version=con.rsrv_version
16
+ ct=packet.cont
17
+ if ct.nil? or ct.length!=32+3*4
18
+ raise "Invalid response to session detach request."
19
+ end
20
+ @port=get_int(ct,4)
21
+ @key=ct[12,32]
22
+ end
23
+ def attach
24
+ c=Rserve::Connection.new(:session=>self)
25
+ @attach_packet=c.rt.request(:cmd=>-1,:cont=>[])
26
+ c
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,37 @@
1
+ require File.dirname(__FILE__)+"/spec_helper.rb"
2
+ require 'rbconfig'
3
+ describe "Rserve::Connection on unix" do
4
+ before do
5
+ @r=Rserve::Connection.new
6
+ end
7
+ if RbConfig::CONFIG['arch']!~/mswin/
8
+ it "method eval_void should raise an error with an incorrect expression" do
9
+ lambda {@r.void_eval("x<-")}.should raise_exception(Rserve::Connection::EvalError) {|e| e.request_packet.stat.should==2}
10
+ lambda {@r.void_eval("as.stt(c(1))")}.should raise_exception(Rserve::Connection::EvalError) {|e|
11
+ e.request_packet.stat.should==127}
12
+ end
13
+ it "method eval should raise an error with an incorrect expression" do
14
+ lambda {@r.eval("x<-")}.should raise_exception(Rserve::Connection::EvalError) {|e| e.request_packet.stat.should==2}
15
+ lambda {@r.eval("as.stt(c(1))")}.should raise_exception(Rserve::Connection::EvalError) {|e|
16
+ e.request_packet.stat.should==127}
17
+ end
18
+ it "should raise ServerNotAvailable if started another instance on another port" do
19
+ lambda {Rserve::Connection.new(:port_number=>6700)}.should raise_exception(Rserve::Connection::ServerNotAvailable)
20
+ end
21
+ it "should create different session on *nix" do
22
+ s=Rserve::Connection.new
23
+ @r.assign("a", 1)
24
+ s.assign("a",2)
25
+ @r.eval('a').to_i.should==1
26
+ s.eval('a').to_i.should==2
27
+ s.close
28
+ end
29
+ else
30
+ it "shouldn't crash server with an incorrect expression as Windows version does"
31
+ it "shouldn't raise ServerNotAvailable if started another instance on another port as Windows version does"
32
+ it "shouldn create a different session. On Windows, every new connection closes previously open session"
33
+ end
34
+
35
+ end
36
+
37
+
@@ -10,9 +10,6 @@ describe Rserve::Connection do
10
10
  @r.last_error.should=="OK"
11
11
  @r.rt.should be_instance_of(Rserve::Talk)
12
12
  end
13
- it "should raise ServerNotAvailable if started another instance on another port" do
14
- lambda {Rserve::Connection.new(:port_number=>6700)}.should raise_exception(Rserve::Connection::ServerNotAvailable)
15
- end
16
13
  it "should quit correctly" do
17
14
  @r.should be_connected
18
15
  @r.close.should be_true
@@ -35,24 +32,31 @@ describe Rserve::Connection do
35
32
  it "method eval_void should return true with correct expression" do
36
33
  @r.void_eval("x<-1").should be_true
37
34
  end
38
- it "method eval_void should raise an error with an incorrect expression" do
39
- lambda {@r.void_eval("x<-")}.should raise_exception(Rserve::Connection::EvalError) {|e| e.request_packet.stat.should==2}
40
- lambda {@r.void_eval("as.stt(c(1))")}.should raise_exception(Rserve::Connection::EvalError) {|e|
41
- e.request_packet.stat.should==127}
42
- end
43
-
35
+
44
36
  it "method eval should return a simple object" do
45
37
  la=@r.eval("TRUE")
46
38
  la.should be_instance_of(Rserve::REXP::Logical)
47
39
  la.true?.should==[true]
48
40
  end
49
-
50
- it "method eval should raise an error with an incorrect expression" do
51
- lambda {@r.eval("x<-")}.should raise_exception(Rserve::Connection::EvalError) {|e| e.request_packet.stat.should==2}
52
- lambda {@r.eval("as.stt(c(1))")}.should raise_exception(Rserve::Connection::EvalError) {|e|
53
- e.request_packet.stat.should==127}
41
+ it "should eval_void_detach correctly" do
42
+ s=@r.void_eval_detach("x<-c(TRUE,FALSE)")
43
+ @r.should_not be_connected
44
+ s.should be_instance_of(Rserve::Session)
45
+ s.host.should==@r.hostname
46
+ s.key.size.should==32
47
+ end
48
+ it "should detach correctly" do
49
+ x=rand(100)
50
+ @r.void_eval("x<-#{x}")
51
+ s=@r.detach
52
+ @r.should_not be_connected
53
+ s.should be_instance_of(Rserve::Session)
54
+ s.host.should==@r.hostname
55
+ s.key.size.should==32
56
+ r=s.attach
57
+ r.eval("x").to_ruby==x
54
58
  end
55
-
59
+
56
60
  it "should eval_void and eval correctly" do
57
61
  @r.void_eval("x<-c(TRUE,FALSE)").should be_true
58
62
  la=@r.eval("x")
@@ -68,8 +72,10 @@ describe Rserve::Connection do
68
72
  describe "assign using REXPs" do
69
73
  before do
70
74
  @r=Rserve::Connection.new
71
-
72
75
  end
76
+ after do
77
+ @r.close
78
+ end
73
79
  it "should assign double" do
74
80
  rexp=Rserve::REXP::Double.new([1.5,-1.5])
75
81
  @r.assign("x", rexp)
@@ -44,6 +44,7 @@ describe Rserve::Protocol do
44
44
  buffer=[0xFF,0x78,0x56,0x34,0x12]
45
45
  expected=0x12345678
46
46
  @t.get_int(buffer,1).should==expected
47
+ @t.get_int(buffer,1).should==@t.get_int_original(buffer,1)
47
48
 
48
49
  # Version with errors
49
50
 
@@ -51,6 +52,9 @@ describe Rserve::Protocol do
51
52
  expected=0x12345678
52
53
  @t.get_int(buffer,1).should==expected
53
54
  end
55
+
56
+
57
+
54
58
  it "get_len method should return correct length from a header" do
55
59
  cmd=Rserve::Protocol::CMD_login
56
60
  len=0x12345678
@@ -61,6 +65,7 @@ describe Rserve::Protocol do
61
65
  buffer=[0xFF,0x78,0x56,0x34,0x12,0x78,0x56,0x34,0x12]
62
66
  expected=0x1234567812345678
63
67
  @t.get_long(buffer,1).should==expected
68
+ @t.get_long(buffer,1).should==@t.get_long_original(buffer,1)
64
69
 
65
70
  end
66
71
  it "set_long method should set correct long(32 bits) for a given buffer" do
@@ -5,6 +5,9 @@ describe "Rserve::REXP#to_ruby" do
5
5
  before do
6
6
  @r=Rserve::Connection.new
7
7
  end
8
+ after do
9
+ @r.close
10
+ end
8
11
  it "should return a Fixnum with vector with one integer element" do
9
12
  @r.eval("1").to_ruby.should==1
10
13
  end
@@ -7,7 +7,9 @@ describe Rserve::Protocol::REXPFactory do
7
7
  before do
8
8
  @r=Rserve::Connection.new
9
9
  end
10
-
10
+ after do
11
+ @r.close
12
+ end
11
13
  it "should process null" do
12
14
  la=@r.eval("NULL")
13
15
  la.should be_instance_of(Rserve::REXP::Null)
@@ -29,6 +31,7 @@ describe Rserve::Protocol::REXPFactory do
29
31
  end
30
32
  it "should process logical vectors with NA" do
31
33
  la=@r.eval("c(TRUE,NA)")
34
+
32
35
  la.should be_instance_of(Rserve::REXP::Logical)
33
36
  la.na?.should==[false,true]
34
37
  end
@@ -5,6 +5,9 @@ describe Rserve::Rlist do
5
5
  @r=Rserve::Connection.new
6
6
  @l=@r.eval("list(name='Fred',age=30,10,20,kids=c(1,2,3))").as_list
7
7
  end
8
+ after do
9
+ @r.close
10
+ end
8
11
  it "method names return correct names" do
9
12
  @l.names.should==['name','age',"","","kids"]
10
13
  end
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__)+"/spec_helper.rb"
2
+ describe Rserve::Session do
3
+ before do
4
+ @r=Rserve::Connection.new
5
+ end
6
+ it "should resume an detached session with void_eval_detach" do
7
+ x2=10+rand(12)
8
+ s=@r.void_eval_detach("x<-1:#{x2}")
9
+ r=Rserve::Connection.new
10
+ r.void_eval("x<-1")
11
+ r.eval("x").to_ruby.should==1
12
+ s.should be_instance_of(Rserve::Session)
13
+ r2=s.attach
14
+ r2.eval("x").to_ruby.should==(1..x2).to_a
15
+ end
16
+ it "should resume an detached session with detach" do
17
+ x2=10+rand(12)
18
+ @r.void_eval("x<-1:#{x2}")
19
+ s=@r.detach
20
+ r=Rserve::Connection.new
21
+ r.void_eval("x<-1")
22
+ r.eval("x").to_ruby.should==1
23
+ s.should be_instance_of(Rserve::Session)
24
+ r2=s.attach
25
+ r2.eval("x").to_ruby.should==(1..x2).to_a
26
+ end
27
+ end
@@ -4,6 +4,9 @@ describe Rserve do
4
4
  before do
5
5
  @r=Rserve::Connection.new()
6
6
  end
7
+ after do
8
+ @r.close
9
+ end
7
10
  it "should calcule a basic LR without hazzle" do
8
11
  script=<<-EOF
9
12
  ## Disease severity as a function of temperature
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
8
- - 9
9
- version: 0.1.9
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Claudio Bustos
@@ -35,7 +35,7 @@ cert_chain:
35
35
  rpP0jjs0
36
36
  -----END CERTIFICATE-----
37
37
 
38
- date: 2010-06-04 00:00:00 -04:00
38
+ date: 2010-06-16 00:00:00 -04:00
39
39
  default_executable:
40
40
  dependencies:
41
41
  - !ruby/object:Gem::Dependency
@@ -62,8 +62,8 @@ dependencies:
62
62
  segments:
63
63
  - 2
64
64
  - 6
65
- - 0
66
- version: 2.6.0
65
+ - 1
66
+ version: 2.6.1
67
67
  type: :development
68
68
  version_requirements: *id002
69
69
  description: |-
@@ -88,6 +88,10 @@ files:
88
88
  - Manifest.txt
89
89
  - README.txt
90
90
  - Rakefile
91
+ - benchmark/benchmark.rb
92
+ - benchmark/comparison_2010_06_07.xls
93
+ - benchmark/comparison_2010_06_07_using_pack.xls
94
+ - benchmark/plot.rb
91
95
  - data/gettysburg.txt
92
96
  - examples/gettysburg.rb
93
97
  - examples/hello_world.rb
@@ -120,9 +124,11 @@ files:
120
124
  - lib/rserve/rexp/wrapper.rb
121
125
  - lib/rserve/rfactor.rb
122
126
  - lib/rserve/rlist.rb
127
+ - lib/rserve/session.rb
123
128
  - lib/rserve/talk.rb
124
129
  - lib/rserve/withattributes.rb
125
130
  - lib/rserve/withnames.rb
131
+ - spec/rserve_connection_on_unix_spec.rb
126
132
  - spec/rserve_connection_spec.rb
127
133
  - spec/rserve_double_spec.rb
128
134
  - spec/rserve_genericvector_spec.rb
@@ -136,6 +142,7 @@ files:
136
142
  - spec/rserve_rexpfactory_spec.rb
137
143
  - spec/rserve_rfactor_spec.rb
138
144
  - spec/rserve_rlist_spec.rb
145
+ - spec/rserve_session_spec.rb
139
146
  - spec/rserve_spec.rb
140
147
  - spec/rserve_talk_spec.rb
141
148
  - spec/rserve_withnames_spec.rb
@@ -181,11 +188,13 @@ test_files:
181
188
  - spec/rserve_double_spec.rb
182
189
  - spec/rserve_withnames_spec.rb
183
190
  - spec/rserve_packet_spec.rb
191
+ - spec/rserve_connection_on_unix_spec.rb
184
192
  - spec/rserve_rexpfactory_spec.rb
185
193
  - spec/rserve_rexp_spec.rb
186
194
  - spec/rserve_integer_spec.rb
187
195
  - spec/rserve_spec.rb
188
196
  - spec/rserve_protocol_spec.rb
189
197
  - spec/rserve_genericvector_spec.rb
198
+ - spec/rserve_session_spec.rb
190
199
  - spec/rserve_logical_spec.rb
191
200
  - spec/rserve_talk_spec.rb
metadata.gz.sig CHANGED
Binary file