rserve-client 0.1.9 → 0.2.0

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.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