rinruby-edge 2.1.0.edge.1

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.
@@ -0,0 +1,24 @@
1
+ #=RinRuby: Accessing the R[http://www.r-project.org] interpreter from pure Ruby
2
+ #
3
+ #RinRuby is a Ruby library that integrates the R interpreter in Ruby, making R's statistical routines and graphics available within Ruby. The library consists of a single Ruby script that is simple to install and does not require any special compilation or installation of R. Since the library is 100% pure Ruby, it works on a variety of operating systems, Ruby implementations, and versions of R. RinRuby's methods are simple, making for readable code. The {website [rinruby.ddahl.org]}[http://rinruby.ddahl.org] describes RinRuby usage, provides comprehensive documentation, gives several examples, and discusses RinRuby's implementation.
4
+ #
5
+
6
+ if defined?(R)
7
+ require 'rinruby'
8
+ else
9
+ R = :dummy
10
+ require 'rinruby'
11
+ Object::send(:remove_const, :R)
12
+ end
13
+
14
+ class RinRubyWithoutRConstant < RinRuby
15
+ DEFAULT_PORT_NUMBER = 38542
16
+ def initialize(*args)
17
+ if args.size == 1 and args[0].kind_of?(Hash) then
18
+ args[0][:port_number] ||= DEFAULT_PORT_NUMBER
19
+ else
20
+ args[3] ||= DEFAULT_PORT_NUMBER
21
+ end
22
+ super(*args)
23
+ end
24
+ end
data/rinruby.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ require_relative 'lib/rinruby/version'
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "rinruby-edge"
6
+ spec.version = RinRuby::VERSION
7
+ spec.authors = ["David Dahl", "Scott Crawford", "Claudio Bustos"]
8
+ spec.email = ["rinruby@ddahl.org", "scott@ddahl.org", "clbustos@gmail.com"]
9
+ spec.summary = %q{RinRuby is a Ruby library that integrates the R interpreter in Ruby}
10
+ spec.description = %q{RinRuby is a Ruby library that integrates the R interpreter in Ruby, making R's statistical routines and graphics available within Ruby. The library consists of a single Ruby script that is simple to install and does not require any special compilation or installation of R. Since the library is 100% pure Ruby, it works on a variety of operating systems, Ruby implementations, and versions of R. RinRuby's methods are simple, making for readable code. The {website [rinruby.ddahl.org]}[http://rinruby.ddahl.org] describes RinRuby usage, provides comprehensive documentation, gives several examples, and discusses RinRuby's implementation.}
11
+ spec.homepage = "http://rinruby.ddahl.org"
12
+ spec.license = "GPL-3.0"
13
+
14
+ spec.files = `git ls-files`.split($/)
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "rake"
20
+ spec.add_development_dependency "rspec", ">= 3.0"
21
+ spec.add_development_dependency "simplecov"
22
+ end
@@ -0,0 +1,441 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'rinruby'
3
+ puts "RinRuby #{RinRuby::VERSION} specification"
4
+
5
+ shared_examples 'RinRubyCore' do
6
+ let(:params){
7
+ {
8
+ :echo_enabled => false,
9
+ :interactive => false,
10
+ :executable => nil,
11
+ :port_number => 38500,
12
+ :port_width => 1000,
13
+ }
14
+ }
15
+ describe "on init" do
16
+ after{(r.quit rescue nil) if defined?(r)}
17
+ it "should accept parameters as specified on Dahl & Crawford(2009)" do
18
+ expect(r.echo_enabled).to be_falsy
19
+ expect(r.interactive).to be_falsy
20
+ case r.instance_variable_get(:@platform)
21
+ when /^windows-cygwin/ then
22
+ expect(r.executable).to match(/(^R|Rterm\.exe["']?)$/)
23
+ when /^windows/ then
24
+ expect(r.executable).to match(/Rterm\.exe["']?$/)
25
+ else
26
+ expect(r.executable).to eq("R")
27
+ end
28
+ end
29
+ it "should accept :echo and :interactive parameters" do
30
+ params.merge!(:echo_enabled => true, :interactive => true)
31
+ expect(r.echo_enabled).to be_truthy
32
+ expect(r.interactive).to be_truthy
33
+ end
34
+ it "should accept custom :port_number" do
35
+ params.merge!(:port_number => 38442+rand(3), :port_width => 1)
36
+ expect(r.port_number).to eq(params[:port_number])
37
+ end
38
+ it "should accept custom :port_width" do
39
+ params.merge!(:port_number => 38442, :port_width => rand(10)+1)
40
+ expect(r.port_width).to eq(params[:port_width])
41
+ expect(r.port_number).to satisfy {|v|
42
+ ((params[:port_number])...(params[:port_number] + params[:port_width])).include?(v)
43
+ }
44
+ end
45
+ end
46
+
47
+ describe "R interface" do
48
+ # In before(:each) or let(including subject) blocks, Assignment to instance variable
49
+ # having a same name defined in before(:all) will not work intentionally,
50
+ # because a new instance variable will be created for the following examples.
51
+ # For workaround, two-step indirect assignment to a hash created in before(:all) is applied.
52
+ before(:all){@cached_env = {:r => nil}} # make placeholder
53
+ subject{@cached_env[:r] ||= r}
54
+ after(:all){@cached_env[:r].quit rescue nil}
55
+ describe "basic methods" do
56
+ it {is_expected.to respond_to(:eval)}
57
+ it {is_expected.to respond_to(:assign)}
58
+ it {is_expected.to respond_to(:pull)}
59
+ it {is_expected.to respond_to(:quit)}
60
+ it {is_expected.to respond_to(:echo)}
61
+ it {is_expected.to respond_to(:prompt)}
62
+ it "return true for complete? for correct expressions" do
63
+ ["", "x<-1", "x<-\n1", "'123\n456'", "1+\n2+\n3"].each{|str|
64
+ expect(subject.complete?(str)).to be true
65
+ }
66
+ end
67
+ it "return false for complete? for incorrect expressions" do
68
+ ["x<-", "'123\n", "1+\n2+\n"].each{|str|
69
+ expect(subject.complete?(str)).to be false
70
+ }
71
+ end
72
+ it "raise error for complete? for unrecoverable expression" do
73
+ [";", "x<-;"].each{|str|
74
+ expect{subject.complete?(str)}.to raise_error(RinRuby::ParseError)
75
+ }
76
+ end
77
+ it "correct eval should return true" do
78
+ ["", "x<-1", "x<-\n1", "'123\n456'"].each{|str|
79
+ expect(subject.eval(str)).to be_truthy
80
+ }
81
+ end
82
+ it "incorrect eval should raise an ParseError" do
83
+ [
84
+ "x<-", "'123\n", # incomplete
85
+ ";", "x<-;", # unrecoverable
86
+ ].each{|str|
87
+ expect{subject.eval(str)}.to raise_error(RinRuby::ParseError)
88
+ }
89
+ end
90
+ end
91
+
92
+ def gen_matrix_cmp_per_elm_proc(&cmp_proc)
93
+ proc{|a, b|
94
+ expect(a.row_size).to eql(b.row_size)
95
+ expect(a.column_size).to eql(b.column_size)
96
+ a.row_size.times{|i|
97
+ a.column_size.times{|j|
98
+ cmp_proc.call(a[i,j], b[i,j])
99
+ }
100
+ }
101
+ }
102
+ end
103
+
104
+ context "on pull" do
105
+ it "should pull a Character" do
106
+ ['Value', ''].each{|v| # normal string and zero-length string
107
+ subject.eval("x<-'#{v}'")
108
+ expect(subject.pull('x')).to eql(v)
109
+ }
110
+ subject.eval("x<-as.character(NA)")
111
+ expect(subject.pull('x')).to eql(nil)
112
+ end
113
+ it "should pull an Integer" do
114
+ [0x12345678, -0x12345678].each{|v| # for check endian, and range
115
+ subject.eval("x<-#{v}L")
116
+ expect(subject.pull('x')).to eql(v)
117
+ }
118
+ end
119
+ it "should pull a Double" do
120
+ [1.5, 1.0].each{|v|
121
+ subject.eval("x<-#{v}e0")
122
+ expect(subject.pull('x')).to eql(v)
123
+ }
124
+ [1 << 32, -(1 << 32)].each{|v| # big integer will be treated as double
125
+ subject.eval("x<-#{v}")
126
+ expect(subject.pull('x')).to eql(v.to_f)
127
+ }
128
+ subject.eval("x<-NaN")
129
+ expect(subject.pull('x').nan?).to be_truthy
130
+ subject.eval("x<-as.numeric(NA)")
131
+ expect(subject.pull('x')).to eql(nil)
132
+ end
133
+ it "should pull a Logical" do
134
+ {:T => true, :F => false, :NA => nil}.each{|k, v|
135
+ subject.eval("x<-#{k}")
136
+ expect(subject.pull('x')).to eql(v)
137
+ }
138
+ end
139
+ it "should pull an Array of Character" do
140
+ {
141
+ "c('a','b','',NA)" => ['a','b','',nil],
142
+ "as.character(NULL)" => [],
143
+ }.each{|k, v|
144
+ subject.eval("x<-#{k}")
145
+ expect(subject.pull('x')).to eql(v)
146
+ }
147
+ end
148
+ it "should pull an Array of Integer" do
149
+ {
150
+ "c(1L,2L,-5L,-3L,NA)" => [1,2,-5,-3,nil],
151
+ "as.integer(NULL)" => [],
152
+ }.each{|k, v|
153
+ subject.eval("x<-#{k}")
154
+ expect(subject.pull('x')).to eql(v)
155
+ }
156
+ end
157
+ it "should pull an Array of Double" do
158
+ subject.eval("x<-c(1.1,2.2,5,3,NA,NaN)") # auto-conversion to numeric vector
159
+ expect(subject.pull('x')[0..-2]).to eql([1.1,2.2,5.0,3.0,nil])
160
+ expect(subject.pull('x')[-1].nan?).to be_truthy
161
+
162
+ subject.eval("x<-c(1L,2L,5L,3.0,NA,NaN)") # auto-conversion to numeric vector
163
+ expect(subject.pull('x')[0..-2]).to eql([1.0,2.0,5.0,3.0,nil])
164
+ expect(subject.pull('x')[-1].nan?).to be_truthy
165
+
166
+ subject.eval("x<-as.numeric(NULL)")
167
+ expect(subject.pull('x')).to eql([])
168
+ end
169
+ it "should pull an Array of Logical" do
170
+ {
171
+ "c(T, F, NA)" => [true, false, nil],
172
+ "as.logical(NULL)" => [],
173
+ }.each{|k, v|
174
+ subject.eval("x<-#{k}")
175
+ expect(subject.pull('x')).to eql(v)
176
+ }
177
+ end
178
+
179
+ it "should pull a Matrix" do
180
+ threshold = 1e-8
181
+ [
182
+ proc{ # integer matrix
183
+ v = rand(100000000) # get 8 digits
184
+ [v, "#{v}L"]
185
+ },
186
+ [ # double matrix
187
+ proc{
188
+ v = rand(100000000) # get 8 digits
189
+ [Float("0.#{v}"), "0.#{v}"]
190
+ },
191
+ gen_matrix_cmp_per_elm_proc{|a, b|
192
+ expect(a).to be_within(threshold).of(b)
193
+ }
194
+ ],
195
+ ].each{|gen_proc, cmp_proc|
196
+ nrow, ncol = [10, 10] # 10 x 10 small matrix
197
+ subject.eval("x<-matrix(nrow=#{nrow}, ncol=#{ncol})")
198
+ rx = Matrix[*((1..nrow).collect{|i|
199
+ (1..ncol).collect{|j|
200
+ v_rb, v_R = gen_proc.call
201
+ subject.eval("x[#{i},#{j}]<-#{v_R}")
202
+ v_rb
203
+ }
204
+ })]
205
+ (cmp_proc || proc{|a, b| expect(a).to eql(b)}).call(subject.pull('x'), rx)
206
+ }
207
+ end
208
+
209
+ it "should pull partially" do
210
+ subject.eval("x<-c(1L,2L,-5L,-3L,NA)")
211
+ [1,2,-5,-3,nil].each.with_index{|v, i|
212
+ expect(subject.pull("x[[#{i + 1}]]")).to eql(v)
213
+ }
214
+ end
215
+
216
+ it "should be the same using pull than R# methods" do
217
+ subject.eval("x <- #{rand(100000000)}")
218
+ expect(subject.pull("x")).to eql(subject.x)
219
+ end
220
+ it "should raise an NoMethod error on getter with 1 or more parameters" do
221
+ expect{subject.unknown_method(1)}.to raise_error(NoMethodError)
222
+ end
223
+ end
224
+
225
+ context "on assign (PREREQUISITE: all pull tests are passed)" do
226
+ it "should assign a Character" do
227
+ x = 'Value'
228
+ subject.assign("x", x)
229
+ expect(subject.pull('x')).to eql(x)
230
+ end
231
+ it "should assign an Integer" do
232
+ [0x12345678, -0x12345678].each{|x|
233
+ subject.assign("x", x)
234
+ expect(subject.pull('x')).to eql(x)
235
+ }
236
+ end
237
+ it "should assign a Double" do
238
+ [rand, 1 << 32, -(1 << 32)].each{|x|
239
+ subject.assign("x", x)
240
+ expect(subject.pull('x')).to eql(x.to_f)
241
+ }
242
+ subject.assign("x", Float::NAN)
243
+ expect(subject.pull('x').nan?).to be_truthy
244
+ end
245
+ it "should assign a Logical" do
246
+ [true, false, nil].each{|x|
247
+ subject.assign("x", x)
248
+ expect(subject.pull('x')).to eql(x)
249
+ }
250
+ end
251
+ it "should assign an Array of Character" do
252
+ x = ['a', 'b', nil]
253
+ subject.assign("x", x)
254
+ expect(subject.pull('x')).to eql(x)
255
+ end
256
+ it "should assign an Array of Integer" do
257
+ x = [1, 2, -5, -3, nil]
258
+ subject.assign("x", x)
259
+ expect(subject.pull('x')).to eql(x)
260
+ end
261
+ it "should assign an Array of Double" do
262
+ x = [rand(100000000), rand(0x1000) << 32, # Integer
263
+ rand, Rational(rand(1000), rand(1000) + 1), # Numeric except for Complex with available .to_f
264
+ nil, Float::NAN]
265
+ subject.assign("x", x)
266
+ expect(subject.pull('x')[0..-2]).to eql(x[0..-3].collect{|v| v.to_f} + [nil])
267
+ expect(subject.pull('x')[-1].nan?).to be_truthy
268
+ end
269
+ it "should assign an Array of Logical" do
270
+ x = [true, false, nil]
271
+ subject.assign("x", x)
272
+ expect(subject.pull('x')).to eql(x)
273
+ end
274
+
275
+ it "should assign a Matrix" do
276
+ threshold = Float::EPSILON * 100
277
+ [
278
+ proc{rand(100000000)}, # integer matrix
279
+ proc{v = rand(100000000); v > 50000000 ? nil : v}, # integer matrix with NA
280
+ [ # double matrix
281
+ proc{rand},
282
+ gen_matrix_cmp_per_elm_proc{|a, b|
283
+ expect(a).to be_within(threshold).of(b)
284
+ },
285
+ ],
286
+ [ # double matrix with NA
287
+ proc{v = rand; v > 0.5 ? nil : v},
288
+ gen_matrix_cmp_per_elm_proc{|a, b|
289
+ if b.kind_of?(Numeric) then
290
+ expect(a).to be_within(threshold).of(b)
291
+ else
292
+ expect(a).to eql(nil)
293
+ end
294
+ },
295
+ ],
296
+ ].each{|gen_proc, cmp_proc|
297
+ x = Matrix::build(100, 200){|i, j| gen_proc.call} # 100 x 200 matrix
298
+ subject.assign("x", x)
299
+ (cmp_proc || proc{|a, b| expect(a).to eql(b)}).call(subject.pull('x'), x)
300
+ }
301
+ end
302
+
303
+ it "should assign partially" do
304
+ x = [1, 2, -5, -3, nil]
305
+ subject.assign("x", x)
306
+ expect(subject.pull('x')).to eql(x)
307
+ subject.assign("x[[3]]", x[2] *= 10)
308
+ expect(subject.pull('x')).to eql(x)
309
+ end
310
+
311
+ it "should be the same using assign than R#= methods" do
312
+ x = rand(100000000)
313
+ subject.assign("x1", x)
314
+ subject.x2 = x
315
+ expect(subject.pull("x1")).to eql(subject.pull("x2"))
316
+ end
317
+ it "should raise an ArgumentError error on setter with 0 parameters" do
318
+ expect{subject.unknown_method=() }.to raise_error(ArgumentError)
319
+ end
320
+ end
321
+ end
322
+
323
+ describe "echo changes eval output" do
324
+ def check_output(echo_args, stdout, stderr)
325
+ r.echo(*echo_args)
326
+ expect{r.eval("write('out', stdout())")}.to output(stdout ? /^out/ : "").to_stdout
327
+ expect{r.eval("write('err', stderr())")}.to output(stderr ? /^err/ : "").to_stdout
328
+ end
329
+ it "should output both stdout and stderr when echo(true, true)" do
330
+ check_output([true, true], true, true)
331
+ end
332
+ it "should output stdout only when echo(true, false)" do
333
+ check_output([true, false], true, false)
334
+ end
335
+ it "should output nothing when echo(false)" do
336
+ check_output(false, false, false)
337
+ end
338
+ end
339
+
340
+ context "on eval in interactive mode" do
341
+ let(:params){
342
+ super().merge({:interactive => true})
343
+ }
344
+ it "should be interrupted by SIGINT" do
345
+ if r.instance_variable_get(:@platform) =~ /java$/ then
346
+ pending("JRuby does not give fully support for signal handling")
347
+ fail
348
+ end
349
+ int_invoked = false
350
+ int_handler = Signal::trap(:INT){int_invoked = true}
351
+ printed = []
352
+ eval_res = r.eval(<<-__TEXT__){|line|
353
+ for(i in 1:10){
354
+ print(i)
355
+ Sys.sleep(1)
356
+ }
357
+ __TEXT__
358
+ line =~ /^\[1\] *(\S+)/
359
+ printed << Integer($1)
360
+ Process::kill(:INT, $$) if (printed[-1] > 2)
361
+ }
362
+ Signal::trap(:INT, int_handler)
363
+ expect(int_invoked).to be_truthy
364
+ expect(eval_res).to be_falsy
365
+ expect(printed).not_to include(10)
366
+ end
367
+ end
368
+
369
+ context "on prompt" do
370
+ let(:params){
371
+ super().merge({:interactive => true})
372
+ }
373
+ let(:input){@input ||= []}
374
+ before(:all){
375
+ begin
376
+ require 'readline'
377
+ rescue LoadError
378
+ end
379
+ }
380
+ before(:each){
381
+ allow(Readline).to receive(:readline){|prompt, add_hist|
382
+ print(prompt)
383
+ input.shift
384
+ } if defined?(Readline)
385
+ allow(r).to receive(:gets){input.shift}
386
+ r.echo(true, true)
387
+ }
388
+ it "should exit with exit() input" do
389
+ ['exit()', ' exit ( ) '].each{|str|
390
+ input.replace([str])
391
+ expect{r.prompt}.to output(/^> /).to_stdout
392
+ }
393
+ end
394
+ it "should respond normally with correct inputs" do
395
+ [
396
+ [['1'], "> [1] 1"],
397
+ [['1 +', '2'], "> + [1] 3"],
398
+ [['1 +', '2 +', '3'], "> + + [1] 6"],
399
+ [['a <- 1'], "> "],
400
+ [['a <-', '1'], "> + "],
401
+ ].each{|src, dst|
402
+ input.replace(src + ['exit()'])
403
+ expect{r.prompt}.to output(/^#{Regexp::escape(dst)}/).to_stdout
404
+ }
405
+ end
406
+ it "should print error gently with incorrect inputs" do
407
+ [
408
+ ['1 +;'],
409
+ ['a <-;'],
410
+ ].each{|src|
411
+ input.replace(src + ['exit()'])
412
+ expect{r.prompt}.to output(/Unrecoverable parse error/).to_stdout
413
+ }
414
+ end
415
+ it "should print R error gently" do
416
+ [
417
+ ['stop("something wrong!"); print("skip")', 'print("do other")'],
418
+ ].each{|src|
419
+ input.replace(src + ['exit()'])
420
+ expect{r.prompt}.to output(/something wrong\!.*(?!skip).*do other/m).to_stdout
421
+ }
422
+ end
423
+ end
424
+
425
+ context "on quit" do
426
+ it "return true" do
427
+ expect(r.quit).to be_truthy
428
+ end
429
+ it "returns an error if used again" do
430
+ r.quit
431
+ expect{r.eval("x=1")}.to raise_error(RinRuby::EngineClosed)
432
+ end
433
+ end
434
+ end
435
+
436
+ describe RinRuby do
437
+ let(:r){
438
+ RinRuby.new(*([:echo_enabled, :interactive, :executable, :port_number, :port_width].collect{|k| params[k]}))
439
+ }
440
+ include_examples 'RinRubyCore'
441
+ end
@@ -0,0 +1,9 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'rinruby_without_r_constant'
3
+
4
+ describe RinRubyWithoutRConstant do
5
+ let(:r){
6
+ RinRubyWithoutRConstant.new(*([:echo_enabled, :interactive, :executable, :port_number, :port_width].collect{|k| params[k]}))
7
+ }
8
+ include_examples 'RinRubyCore'
9
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ -f s
@@ -0,0 +1,35 @@
1
+ require 'simplecov'
2
+ unless ENV['NO_COV']
3
+ SimpleCov.start do
4
+ add_filter '/spec/'
5
+ end
6
+ end
7
+
8
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
9
+ $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
10
+ require 'rspec'
11
+ require 'matrix'
12
+
13
+ RSpec.configure do |config|
14
+ config.expect_with :rspec do |c|
15
+ c.syntax = [:should, :expect]
16
+ end
17
+
18
+ # Use color in STDOUT
19
+ config.color = true
20
+
21
+ # Use color not only in STDOUT but also in pagers and files
22
+ config.tty = true
23
+
24
+ # Use the specified formatter
25
+ config.formatter = :documentation # :progress, :html, :textmate
26
+ end
27
+
28
+
29
+ class String
30
+ def deindent
31
+ gsub /^[ \t]*/, ''
32
+ end
33
+ end
34
+
35
+
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rinruby-edge
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.1.0.edge.1
5
+ platform: ruby
6
+ authors:
7
+ - David Dahl
8
+ - Scott Crawford
9
+ - Claudio Bustos
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2022-07-24 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rake
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: rspec
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '3.0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '3.0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: simplecov
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ description: RinRuby is a Ruby library that integrates the R interpreter in Ruby,
58
+ making R's statistical routines and graphics available within Ruby. The library
59
+ consists of a single Ruby script that is simple to install and does not require
60
+ any special compilation or installation of R. Since the library is 100% pure Ruby,
61
+ it works on a variety of operating systems, Ruby implementations, and versions of
62
+ R. RinRuby's methods are simple, making for readable code. The {website [rinruby.ddahl.org]}[http://rinruby.ddahl.org]
63
+ describes RinRuby usage, provides comprehensive documentation, gives several examples,
64
+ and discusses RinRuby's implementation.
65
+ email:
66
+ - rinruby@ddahl.org
67
+ - scott@ddahl.org
68
+ - clbustos@gmail.com
69
+ executables: []
70
+ extensions: []
71
+ extra_rdoc_files: []
72
+ files:
73
+ - ".appveyor.yml"
74
+ - ".gitignore"
75
+ - ".travis.yml"
76
+ - Gemfile
77
+ - History.txt
78
+ - LICENSE.txt
79
+ - Manifest.txt
80
+ - README.md
81
+ - README_ORIG.md
82
+ - Rakefile
83
+ - lib/rinruby.rb
84
+ - lib/rinruby/version.rb
85
+ - lib/rinruby_without_r_constant.rb
86
+ - rinruby.gemspec
87
+ - spec/rinruby_spec.rb
88
+ - spec/rinruby_without_r_constant_spec.rb
89
+ - spec/spec.opts
90
+ - spec/spec_helper.rb
91
+ homepage: http://rinruby.ddahl.org
92
+ licenses:
93
+ - GPL-3.0
94
+ metadata: {}
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">"
107
+ - !ruby/object:Gem::Version
108
+ version: 1.3.1
109
+ requirements: []
110
+ rubygems_version: 3.3.7
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: RinRuby is a Ruby library that integrates the R interpreter in Ruby
114
+ test_files:
115
+ - spec/rinruby_spec.rb
116
+ - spec/rinruby_without_r_constant_spec.rb
117
+ - spec/spec.opts
118
+ - spec/spec_helper.rb