eval_in 0.1.3 → 0.1.4
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.
- checksums.yaml +4 -4
- data/Readme.md +12 -11
- data/eval_in.gemspec +3 -3
- data/lib/eval_in.rb +49 -16
- data/lib/eval_in/version.rb +1 -1
- data/spec/eval_in_spec.rb +92 -4
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8331a9a20d6f485a925ca9e29ff4daf3c5beebad
|
4
|
+
data.tar.gz: 4c62d600cddd2acf41608da7832a2aa268a5a05e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd354b9ded63f728f01eb81b37952ae8ba97e2ceae8dd7b1d6e7cb76e06eb0d6eb2395ff74902e71f76497ddf470cf0b4dc49331c0153a2ff2f59aeb9ab9dadd
|
7
|
+
data.tar.gz: 0f15ac725abf2c871d3e50bc08244fbc6a2b8c8173bcdeb068ab4c4c7ed99ebeb53e1f3db0c00e11ab38a07bca5d3cddb142679b906086e76ab6654efa4eaf2c
|
data/Readme.md
CHANGED
@@ -24,11 +24,23 @@ result.code # => "puts \"hello, \#{gets}\""
|
|
24
24
|
result.status # => "OK (0.064 sec real, 0.073 sec wall, 9 MB, 21 syscalls)"
|
25
25
|
```
|
26
26
|
|
27
|
+
Docs are [here](http://rdoc.info/gems/eval_in/frames/EvalIn).
|
27
28
|
|
28
29
|
What languages can this run?
|
29
30
|
----------------------------
|
30
31
|
|
31
32
|
<table>
|
33
|
+
<tr>
|
34
|
+
<th align="left">Ruby</th>
|
35
|
+
</td>
|
36
|
+
<td>
|
37
|
+
ruby/mri-1.0<br />
|
38
|
+
ruby/mri-1.8.7<br />
|
39
|
+
ruby/mri-1.9.3<br />
|
40
|
+
ruby/mri-2.0.0<br />
|
41
|
+
ruby/mri-2.1<br />
|
42
|
+
</td>
|
43
|
+
</tr>
|
32
44
|
<tr>
|
33
45
|
<th align="left">C</th>
|
34
46
|
</td>
|
@@ -125,17 +137,6 @@ What languages can this run?
|
|
125
137
|
python/cpython-3.4.1<br />
|
126
138
|
</td>
|
127
139
|
</tr>
|
128
|
-
<tr>
|
129
|
-
<th align="left">Ruby</th>
|
130
|
-
</td>
|
131
|
-
<td>
|
132
|
-
ruby/mri-1.0<br />
|
133
|
-
ruby/mri-1.8.7<br />
|
134
|
-
ruby/mri-1.9.3<br />
|
135
|
-
ruby/mri-2.0.0<br />
|
136
|
-
ruby/mri-2.1<br />
|
137
|
-
</td>
|
138
|
-
</tr>
|
139
140
|
<tr>
|
140
141
|
<th align="left">Slash</th>
|
141
142
|
</td>
|
data/eval_in.gemspec
CHANGED
@@ -14,6 +14,7 @@ Gem::Specification.new do |s|
|
|
14
14
|
|
15
15
|
== Languages and Versions
|
16
16
|
|
17
|
+
Ruby | MRI 1.0, MRI 1.8.7, MRI 1.9.3, MRI 2.0.0, MRI 2.1
|
17
18
|
C | GCC 4.4.3, GCC 4.9.1
|
18
19
|
C++ | C++11 (GCC 4.9.1), GCC 4.4.3, GCC 4.9.1
|
19
20
|
CoffeeScript | CoffeeScript 1.7.1 (Node 0.10.29)
|
@@ -27,7 +28,6 @@ Gem::Specification.new do |s|
|
|
27
28
|
Pascal | Free Pascal 2.6.4
|
28
29
|
Perl | Perl 5.20.0
|
29
30
|
Python | CPython 2.7.8, CPython 3.4.1
|
30
|
-
Ruby | MRI 1.0, MRI 1.8.7, MRI 1.9.3, MRI 2.0.0, MRI 2.1
|
31
31
|
Slash | Slash HEAD
|
32
32
|
x86 Assembly | NASM 2.07
|
33
33
|
|
@@ -35,8 +35,8 @@ Gem::Specification.new do |s|
|
|
35
35
|
|
36
36
|
It's this simple:
|
37
37
|
|
38
|
-
result = EvalIn.call 'puts "
|
39
|
-
result.output # "
|
38
|
+
result = EvalIn.call 'puts "example"', language: "ruby/mri-2.1"
|
39
|
+
result.output # returns "example\\n"
|
40
40
|
|
41
41
|
DESCRIPTION
|
42
42
|
s.license = "WTFPL"
|
data/lib/eval_in.rb
CHANGED
@@ -43,7 +43,11 @@ module EvalIn
|
|
43
43
|
# The data structure containing the final result
|
44
44
|
# its attributes default to null-objects for their given type
|
45
45
|
class Result
|
46
|
-
|
46
|
+
@attribute_names = [:exitstatus, :language, :language_friendly, :code, :output, :status, :url].freeze
|
47
|
+
attr_accessor *@attribute_names
|
48
|
+
class << self
|
49
|
+
attr_reader :attribute_names
|
50
|
+
end
|
47
51
|
|
48
52
|
def initialize(attributes={})
|
49
53
|
attributes = attributes.dup
|
@@ -54,7 +58,15 @@ module EvalIn
|
|
54
58
|
self.output = attributes.delete(:output) || ""
|
55
59
|
self.status = attributes.delete(:status) || ""
|
56
60
|
self.url = attributes.delete(:url) || ""
|
57
|
-
|
61
|
+
stderr = attributes.delete(:stderr) || $stderr
|
62
|
+
stderr.puts "Unexpected attributes! #{attributes.keys.inspect}" if attributes.any?
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns representation of the result built out of JSON primitives (hash, string, int)
|
66
|
+
def as_json
|
67
|
+
self.class.attribute_names.each_with_object Hash.new do |name, attributes|
|
68
|
+
attributes[name.to_s] = public_send name
|
69
|
+
end
|
58
70
|
end
|
59
71
|
end
|
60
72
|
|
@@ -69,7 +81,16 @@ module EvalIn
|
|
69
81
|
# result = EvalIn.call 'puts "hello, #{gets}"', stdin: 'world', language: "ruby/mri-2.1"
|
70
82
|
# result.output # => "hello, world\n"
|
71
83
|
def self.call(code, options={})
|
72
|
-
|
84
|
+
fetch_result post_code(code, options)
|
85
|
+
end
|
86
|
+
|
87
|
+
# @param url [String] the url with the result
|
88
|
+
#
|
89
|
+
# @example
|
90
|
+
# result = EvalIn.fetch_result "https://eval.in/147.json"
|
91
|
+
# result.output # => "Hello Charlie! "
|
92
|
+
def self.fetch_result(url)
|
93
|
+
build_result fetch_result_json jsonify_url url
|
73
94
|
end
|
74
95
|
|
75
96
|
# @api private
|
@@ -94,9 +115,7 @@ module EvalIn
|
|
94
115
|
}
|
95
116
|
|
96
117
|
if result.code == '302'
|
97
|
-
|
98
|
-
location += '.json' unless location.end_with? '.json'
|
99
|
-
location
|
118
|
+
jsonify_url result['location']
|
100
119
|
elsif KNOWN_LANGUAGES.include? language
|
101
120
|
raise RequestError, "There was an unexpected error, we got back a response code of #{result.code}"
|
102
121
|
else
|
@@ -107,20 +126,27 @@ module EvalIn
|
|
107
126
|
|
108
127
|
# @api private
|
109
128
|
def self.fetch_result_json(location)
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
129
|
+
# Can't just use Net::HTTP.get, b/c it doesn't use ssl on 1.9.3
|
130
|
+
# https://github.com/ruby/ruby/blob/v2_1_2/lib/net/http.rb#L478-479
|
131
|
+
# https://github.com/ruby/ruby/blob/v1_9_3_547/lib/net/http.rb#L454
|
132
|
+
uri = URI location
|
133
|
+
Net::HTTP.start(uri.hostname, uri.port, use_ssl: (uri.scheme == 'https')) { |http|
|
134
|
+
body = http.request_get(uri.request_uri).body
|
135
|
+
if body
|
136
|
+
JSON.parse(body).merge('url' => location)
|
137
|
+
else
|
138
|
+
raise ResultNotFound, "No json at #{location.inspect}"
|
139
|
+
end
|
140
|
+
}
|
115
141
|
end
|
116
142
|
|
117
143
|
# @api private
|
118
144
|
def self.build_result(response_json)
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
else
|
145
|
+
exitstatus = case response_json['status']
|
146
|
+
when nil then nil # let it choose default
|
147
|
+
when /status (\d+)$/ then $1.to_i
|
148
|
+
when /^Forbidden/ then 1
|
149
|
+
else 0
|
124
150
|
end
|
125
151
|
|
126
152
|
Result.new exitstatus: exitstatus,
|
@@ -131,4 +157,11 @@ module EvalIn
|
|
131
157
|
status: response_json['status'],
|
132
158
|
url: response_json['url']
|
133
159
|
end
|
160
|
+
|
161
|
+
# @api private
|
162
|
+
def self.jsonify_url(url)
|
163
|
+
uri = URI(url)
|
164
|
+
uri.path = Pathname.new(uri.path).sub_ext('.json').to_s
|
165
|
+
uri.to_s
|
166
|
+
end
|
134
167
|
end
|
data/lib/eval_in/version.rb
CHANGED
data/spec/eval_in_spec.rb
CHANGED
@@ -28,15 +28,26 @@ RSpec.describe EvalIn, integration: true do
|
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'evaluates Ruby code through eval.in' do
|
31
|
-
result = EvalIn.call 'print "hello, #{gets}"', stdin: "world", language: "ruby/mri-1
|
31
|
+
result = EvalIn.call 'print "hello, #{gets}"', stdin: "world", language: "ruby/mri-2.1", context: 'eval_in integration test'
|
32
32
|
expect(result.exitstatus ).to eq 0
|
33
|
-
expect(result.language ).to eq "ruby/mri-1
|
34
|
-
expect(result.language_friendly).to eq "Ruby — MRI 1
|
33
|
+
expect(result.language ).to eq "ruby/mri-2.1"
|
34
|
+
expect(result.language_friendly).to eq "Ruby — MRI 2.1"
|
35
35
|
expect(result.code ).to eq 'print "hello, #{gets}"'
|
36
36
|
expect(result.output ).to eq "hello, world"
|
37
37
|
expect(result.status ).to match /OK \([\d.]+ sec real, [\d.]+ sec wall, \d MB, \d+ syscalls\)/
|
38
38
|
expect(result.url ).to match %r(https://eval.in/\d+.json)
|
39
39
|
end
|
40
|
+
|
41
|
+
it 'fetches previous results from eval.in' do
|
42
|
+
result = EvalIn.fetch_result "https://eval.in/147.json"
|
43
|
+
expect(result.exitstatus ).to eq 0
|
44
|
+
expect(result.language ).to eq "ruby/mri-1.9.3"
|
45
|
+
expect(result.language_friendly).to eq "Ruby — MRI 1.9.3"
|
46
|
+
expect(result.code ).to eq %'class Greeter\r\n def initialize(name)\r\n @name = name\r\n end\r\n\r\n def greet\r\n puts \"Hello \#{@name}!\"\r\n end\r\nend\r\n\r\ngreeter = Greeter.new \"Charlie\"\r\ngreeter.greet'
|
47
|
+
expect(result.output ).to eq "Hello Charlie!\n"
|
48
|
+
expect(result.status ).to match /OK \([\d.]+ sec real, [\d.]+ sec wall, \d MB, \d+ syscalls\)/
|
49
|
+
expect(result.url ).to match %r(https://eval.in/147.json)
|
50
|
+
end
|
40
51
|
end
|
41
52
|
|
42
53
|
RSpec.describe EvalIn::Result do
|
@@ -86,10 +97,32 @@ RSpec.describe EvalIn::Result do
|
|
86
97
|
expect(attributes).to eq status: 'OK'
|
87
98
|
end
|
88
99
|
|
89
|
-
it 'logs extra attributes to
|
100
|
+
it 'logs extra attributes to stderr input' do
|
101
|
+
fake_error_stream = StringIO.new
|
102
|
+
EvalIn::Result.new a: 1, b: 2, stderr: fake_error_stream
|
103
|
+
expect(fake_error_stream.string).to eq "Unexpected attributes! [:a, :b]\n"
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'defaults the error stream to $stderr' do
|
90
107
|
expect { EvalIn::Result.new a: 1, b: 2 }.to \
|
91
108
|
output("Unexpected attributes! [:a, :b]\n").to_stderr
|
92
109
|
end
|
110
|
+
|
111
|
+
it 'has an as_json representation which dumps all its keys' do
|
112
|
+
result = EvalIn::Result.new(language: 'l',
|
113
|
+
language_friendly: 'lf',
|
114
|
+
code: 'c',
|
115
|
+
output: 'o',
|
116
|
+
status: 's',
|
117
|
+
url: 'u')
|
118
|
+
expect(result.as_json).to eq 'exitstatus' => -1,
|
119
|
+
'language' => 'l',
|
120
|
+
'language_friendly' => 'lf',
|
121
|
+
'code' => 'c',
|
122
|
+
'output' => 'o',
|
123
|
+
'status' => 's',
|
124
|
+
'url' => 'u'
|
125
|
+
end
|
93
126
|
end
|
94
127
|
|
95
128
|
|
@@ -271,3 +304,58 @@ RSpec.describe 'build_result' do
|
|
271
304
|
expect(result.exitstatus).to eq 1
|
272
305
|
end
|
273
306
|
end
|
307
|
+
|
308
|
+
|
309
|
+
RSpec.describe 'fetch_result' do
|
310
|
+
include WebMock::API
|
311
|
+
|
312
|
+
def stub_eval_in(url)
|
313
|
+
stub_request(:get, url)
|
314
|
+
.to_return(status: 200, body: json_result)
|
315
|
+
end
|
316
|
+
|
317
|
+
let(:ruby_result) { {'lang' => 'some lang', 'lang_friendly' => 'some lang friendly', 'code' => 'some code', 'output' => 'some output', 'status' => 'some status'} }
|
318
|
+
let(:json_result) { JSON.dump ruby_result }
|
319
|
+
|
320
|
+
it 'wraps fetch_result_json and build_result' do
|
321
|
+
url = 'https://eval.in/1.json'
|
322
|
+
stub_eval_in url
|
323
|
+
result = EvalIn.fetch_result url
|
324
|
+
assert_result result,
|
325
|
+
exitstatus: 0,
|
326
|
+
language: ruby_result['lang'],
|
327
|
+
language_friendly: ruby_result['lang_friendly'],
|
328
|
+
code: ruby_result['code'],
|
329
|
+
output: ruby_result['output'],
|
330
|
+
status: ruby_result['status'],
|
331
|
+
url: url
|
332
|
+
end
|
333
|
+
|
334
|
+
it 'jsonifies the url if it isn\'t already' do
|
335
|
+
stub_eval_in 'https://eval.in/1.json'
|
336
|
+
expect(EvalIn.fetch_result('https://eval.in/1').url).to eq 'https://eval.in/1.json'
|
337
|
+
expect(EvalIn.fetch_result('https://eval.in/1.json').url).to eq 'https://eval.in/1.json'
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
|
342
|
+
RSpec.describe 'jsonify_url' do
|
343
|
+
def assert_transforms(initial_url, expected_url)
|
344
|
+
actual_url = EvalIn.jsonify_url(initial_url)
|
345
|
+
expect(actual_url).to eq expected_url
|
346
|
+
end
|
347
|
+
|
348
|
+
it 'appends .json to a url that is missing it' do
|
349
|
+
assert_transforms 'http://eval.in/1', 'http://eval.in/1.json'
|
350
|
+
assert_transforms 'http://eval.in/1.json', 'http://eval.in/1.json'
|
351
|
+
|
352
|
+
assert_transforms 'http://eval.in/1?a=b', 'http://eval.in/1.json?a=b'
|
353
|
+
assert_transforms 'http://eval.in/1.json?a=b', 'http://eval.in/1.json?a=b'
|
354
|
+
end
|
355
|
+
|
356
|
+
it 'changes .not-json to .json' do
|
357
|
+
assert_transforms 'http://eval.in/1.xml', 'http://eval.in/1.json'
|
358
|
+
assert_transforms 'http://eval.in/1.html', 'http://eval.in/1.json'
|
359
|
+
assert_transforms 'http://eval.in/1.html?a=b', 'http://eval.in/1.json?a=b'
|
360
|
+
end
|
361
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eval_in
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Cheek
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-08-
|
11
|
+
date: 2014-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -43,6 +43,7 @@ description: |+
|
|
43
43
|
|
44
44
|
== Languages and Versions
|
45
45
|
|
46
|
+
Ruby | MRI 1.0, MRI 1.8.7, MRI 1.9.3, MRI 2.0.0, MRI 2.1
|
46
47
|
C | GCC 4.4.3, GCC 4.9.1
|
47
48
|
C++ | C++11 (GCC 4.9.1), GCC 4.4.3, GCC 4.9.1
|
48
49
|
CoffeeScript | CoffeeScript 1.7.1 (Node 0.10.29)
|
@@ -56,7 +57,6 @@ description: |+
|
|
56
57
|
Pascal | Free Pascal 2.6.4
|
57
58
|
Perl | Perl 5.20.0
|
58
59
|
Python | CPython 2.7.8, CPython 3.4.1
|
59
|
-
Ruby | MRI 1.0, MRI 1.8.7, MRI 1.9.3, MRI 2.0.0, MRI 2.1
|
60
60
|
Slash | Slash HEAD
|
61
61
|
x86 Assembly | NASM 2.07
|
62
62
|
|
@@ -64,8 +64,8 @@ description: |+
|
|
64
64
|
|
65
65
|
It's this simple:
|
66
66
|
|
67
|
-
result = EvalIn.call 'puts "
|
68
|
-
result.output # "
|
67
|
+
result = EvalIn.call 'puts "example"', language: "ruby/mri-2.1"
|
68
|
+
result.output # returns "example\n"
|
69
69
|
|
70
70
|
email:
|
71
71
|
- josh.cheek@gmail.com
|
@@ -101,7 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
101
|
version: '0'
|
102
102
|
requirements: []
|
103
103
|
rubyforge_project:
|
104
|
-
rubygems_version: 2.
|
104
|
+
rubygems_version: 2.4.1
|
105
105
|
signing_key:
|
106
106
|
specification_version: 4
|
107
107
|
summary: Evaluates code (Ruby and others) safely by sending it to https://eval.in
|