rinruby-edge 2.1.0.edge.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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