eval_in 0.1.4 → 0.1.5

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/lib/eval_in.rb CHANGED
@@ -11,7 +11,7 @@ module EvalIn
11
11
  ResultNotFound = Class.new EvalInError
12
12
 
13
13
  # @example Generated with
14
- # curl https://eval.in | ruby -rnokogiri -e 'puts Nokogiri::HTML($stdin.read).css("option").map { |o| o["value"] }'
14
+ # nokogiri https://eval.in -e 'puts $_.xpath("//option/@value")'
15
15
  KNOWN_LANGUAGES = %w[
16
16
  c/gcc-4.4.3
17
17
  c/gcc-4.9.1
@@ -81,38 +81,29 @@ module EvalIn
81
81
  # result = EvalIn.call 'puts "hello, #{gets}"', stdin: 'world', language: "ruby/mri-2.1"
82
82
  # result.output # => "hello, world\n"
83
83
  def self.call(code, options={})
84
- fetch_result post_code(code, options)
84
+ url = post_code(code, options)
85
+ fetch_result url, options
85
86
  end
86
87
 
87
88
  # @param url [String] the url with the result
89
+ # @option options [String] :context Will be included in the user agent
88
90
  #
89
91
  # @example
90
92
  # result = EvalIn.fetch_result "https://eval.in/147.json"
91
93
  # result.output # => "Hello Charlie! "
92
- def self.fetch_result(url)
93
- build_result fetch_result_json jsonify_url url
94
+ def self.fetch_result(raw_url, options={})
95
+ raw_json_url = jsonify_url(raw_url)
96
+ build_result fetch_result_json(raw_json_url, options)
94
97
  end
95
98
 
96
99
  # @api private
97
100
  def self.post_code(code, options)
98
- uri = URI(options.fetch(:url, "https://eval.in/"))
101
+ url = options.fetch(:url, "https://eval.in/")
99
102
  input = options.fetch(:stdin, "")
100
103
  language = options.fetch(:language) { raise ArgumentError, ":language is mandatory, but options only has #{options.keys.inspect}" }
101
- user_agent = 'http://rubygems.org/gems/eval_in'
102
- user_agent << " (#{options[:context]})" if options[:context]
103
- path = uri.path
104
- path = '/' if path.empty?
105
-
106
- # stole this out of implementation for post_form https://github.com/ruby/ruby/blob/2afed6eceff2951b949db7ded8167a75b431bad6/lib/net/http.rb#L503
107
- request = Net::HTTP::Post.new(path)
108
- request.form_data = {"utf8" => "√", "code" => code, "execute" => "on", "lang" => language, "input" => input}
109
- request['User-Agent'] = user_agent
110
- request.basic_auth uri.user, uri.password if uri.user
111
- net = Net::HTTP.new(uri.hostname, uri.port)
112
- # net.set_debug_output $stdout
113
- result = Net::HTTP.start(uri.hostname, uri.port, use_ssl: (uri.scheme == 'https')) { |http|
114
- http.request(request)
115
- }
104
+ form_data = {"utf8" => "√", "code" => code, "execute" => "on", "lang" => language, "input" => input}
105
+
106
+ result = post_request url, form_data, user_agent_for(options[:context])
116
107
 
117
108
  if result.code == '302'
118
109
  jsonify_url result['location']
@@ -125,19 +116,10 @@ module EvalIn
125
116
  end
126
117
 
127
118
  # @api private
128
- def self.fetch_result_json(location)
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
- }
119
+ def self.fetch_result_json(raw_url, options={})
120
+ result = get_request raw_url, user_agent_for(options[:context])
121
+ return JSON.parse(result.body).merge('url' => raw_url) if result.body
122
+ raise ResultNotFound, "No json at #{raw_url.inspect}"
141
123
  end
142
124
 
143
125
  # @api private
@@ -164,4 +146,43 @@ module EvalIn
164
146
  uri.path = Pathname.new(uri.path).sub_ext('.json').to_s
165
147
  uri.to_s
166
148
  end
149
+
150
+ # @private
151
+ def self.user_agent_for(context)
152
+ 'http://rubygems.org/gems/eval_in'.tap do |agent|
153
+ context && agent.concat(" (#{context})")
154
+ end
155
+ end
156
+
157
+ # @api private
158
+ # Can't just use Net::HTTP.get, b/c it doesn't use ssl on 1.9.3
159
+ # https://github.com/ruby/ruby/blob/v2_1_2/lib/net/http.rb#L478-479
160
+ # https://github.com/ruby/ruby/blob/v1_9_3_547/lib/net/http.rb#L454
161
+ def self.get_request(raw_url, user_agent)
162
+ generic_request_for raw_url: raw_url,
163
+ request_type: Net::HTTP::Get,
164
+ user_agent: user_agent
165
+ end
166
+
167
+ # @private
168
+ def self.post_request(raw_url, form_data, user_agent)
169
+ generic_request_for raw_url: raw_url,
170
+ request_type: Net::HTTP::Post,
171
+ user_agent: user_agent,
172
+ form_data: form_data
173
+ end
174
+
175
+ # @private
176
+ # stole this out of implementation for post_form https://github.com/ruby/ruby/blob/2afed6eceff2951b949db7ded8167a75b431bad6/lib/net/http.rb#L503
177
+ # can use this to view the request: http.set_debug_output $stdout
178
+ def self.generic_request_for(params)
179
+ uri = URI params.fetch(:raw_url)
180
+ path = uri.path
181
+ path = '/' if path.empty?
182
+ request = params.fetch(:request_type).new(path)
183
+ request['User-Agent'] = params[:user_agent] if params.key? :user_agent
184
+ request.form_data = params[:form_data] if params.key? :form_data
185
+ request.basic_auth uri.user, uri.password if uri.user
186
+ Net::HTTP.start(uri.hostname, uri.port, use_ssl: (uri.scheme == 'https')) { |http| http.request request }
187
+ end
167
188
  end
@@ -1,3 +1,3 @@
1
1
  module EvalIn
2
- VERSION = '0.1.4'
2
+ VERSION = '0.1.5'
3
3
  end
data/spec/eval_in_spec.rb CHANGED
@@ -27,8 +27,10 @@ RSpec.describe EvalIn, integration: true do
27
27
  WebMock.disable_net_connect!
28
28
  end
29
29
 
30
+ let(:context) { 'eval_in integration test' }
31
+
30
32
  it 'evaluates Ruby code through eval.in' do
31
- result = EvalIn.call 'print "hello, #{gets}"', stdin: "world", language: "ruby/mri-2.1", context: 'eval_in integration test'
33
+ result = EvalIn.call 'print "hello, #{gets}"', stdin: "world", language: "ruby/mri-2.1", context: context
32
34
  expect(result.exitstatus ).to eq 0
33
35
  expect(result.language ).to eq "ruby/mri-2.1"
34
36
  expect(result.language_friendly).to eq "Ruby — MRI 2.1"
@@ -48,6 +50,18 @@ RSpec.describe EvalIn, integration: true do
48
50
  expect(result.status ).to match /OK \([\d.]+ sec real, [\d.]+ sec wall, \d MB, \d+ syscalls\)/
49
51
  expect(result.url ).to match %r(https://eval.in/147.json)
50
52
  end
53
+
54
+ it 'is in sync with known languages' do
55
+ # iffy solution, but it's simple and works,
56
+ # Rexml might get taken out of stdlib, so is more likely than this regex to fail in the future,
57
+ # and I don't want to add dep on Nokogiri (w/ libxml & libxslt) where a small regex works adequately
58
+ current_known_languages = EvalIn.get_request('https://eval.in', context)
59
+ .body
60
+ .each_line
61
+ .map { |line| line[/option.*?value="([^"]+)"/, 1] }
62
+ .compact
63
+ expect(EvalIn::KNOWN_LANGUAGES).to eq current_known_languages
64
+ end
51
65
  end
52
66
 
53
67
  RSpec.describe EvalIn::Result do
@@ -309,8 +323,9 @@ end
309
323
  RSpec.describe 'fetch_result' do
310
324
  include WebMock::API
311
325
 
312
- def stub_eval_in(url)
326
+ def stub_eval_in(url, options={})
313
327
  stub_request(:get, url)
328
+ .with(headers: {'User-Agent' => options.fetch(:user_agent, 'http://rubygems.org/gems/eval_in')})
314
329
  .to_return(status: 200, body: json_result)
315
330
  end
316
331
 
@@ -336,6 +351,11 @@ RSpec.describe 'fetch_result' do
336
351
  expect(EvalIn.fetch_result('https://eval.in/1').url).to eq 'https://eval.in/1.json'
337
352
  expect(EvalIn.fetch_result('https://eval.in/1.json').url).to eq 'https://eval.in/1.json'
338
353
  end
354
+
355
+ it 'can take a context for the user agent' do
356
+ stub_eval_in 'https://eval.in/1.json', user_agent: 'http://rubygems.org/gems/eval_in (c)'
357
+ expect(EvalIn.fetch_result('https://eval.in/1', context: 'c').url).to eq 'https://eval.in/1.json'
358
+ end
339
359
  end
340
360
 
341
361
 
metadata CHANGED
@@ -1,80 +1,67 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eval_in
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Josh Cheek
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2014-08-31 00:00:00.000000000 Z
12
+ date: 2014-09-01 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: rspec
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
- - - "~>"
19
+ - - ~>
18
20
  - !ruby/object:Gem::Version
19
21
  version: '3.0'
20
22
  type: :development
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
- - - "~>"
27
+ - - ~>
25
28
  - !ruby/object:Gem::Version
26
29
  version: '3.0'
27
30
  - !ruby/object:Gem::Dependency
28
31
  name: webmock
29
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
30
34
  requirements:
31
- - - "~>"
35
+ - - ~>
32
36
  - !ruby/object:Gem::Version
33
37
  version: '1.18'
34
38
  type: :development
35
39
  prerelease: false
36
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
37
42
  requirements:
38
- - - "~>"
43
+ - - ~>
39
44
  - !ruby/object:Gem::Version
40
45
  version: '1.18'
41
- description: |+
42
- Safely evaluates code (Ruby and others) by sending it through https://eval.in
43
-
44
- == Languages and Versions
45
-
46
- Ruby | MRI 1.0, MRI 1.8.7, MRI 1.9.3, MRI 2.0.0, MRI 2.1
47
- C | GCC 4.4.3, GCC 4.9.1
48
- C++ | C++11 (GCC 4.9.1), GCC 4.4.3, GCC 4.9.1
49
- CoffeeScript | CoffeeScript 1.7.1 (Node 0.10.29)
50
- Fortran | F95 (GCC 4.4.3)
51
- Haskell | Hugs98 September 2006
52
- Io | Io 20131204
53
- JavaScript | Node 0.10.29
54
- Lua | Lua 5.1.5, Lua 5.2.3
55
- OCaml | OCaml 4.01.0
56
- PHP | PHP 5.5.14
57
- Pascal | Free Pascal 2.6.4
58
- Perl | Perl 5.20.0
59
- Python | CPython 2.7.8, CPython 3.4.1
60
- Slash | Slash HEAD
61
- x86 Assembly | NASM 2.07
62
-
63
- == Example:
64
-
65
- It's this simple:
66
-
67
- result = EvalIn.call 'puts "example"', language: "ruby/mri-2.1"
68
- result.output # returns "example\n"
69
-
46
+ description: ! "Safely evaluates code (Ruby and others) by sending it through https://eval.in\n\n==
47
+ Languages and Versions\n\n Ruby | MRI 1.0, MRI 1.8.7, MRI 1.9.3, MRI 2.0.0,
48
+ MRI 2.1\n C | GCC 4.4.3, GCC 4.9.1\n C++ | C++11 (GCC 4.9.1),
49
+ GCC 4.4.3, GCC 4.9.1\n CoffeeScript | CoffeeScript 1.7.1 (Node 0.10.29)\n Fortran
50
+ \ | F95 (GCC 4.4.3)\n Haskell | Hugs98 September 2006\n Io |
51
+ Io 20131204\n JavaScript | Node 0.10.29\n Lua | Lua 5.1.5, Lua 5.2.3\n
52
+ \ OCaml | OCaml 4.01.0\n PHP | PHP 5.5.14\n Pascal |
53
+ Free Pascal 2.6.4\n Perl | Perl 5.20.0\n Python | CPython 2.7.8,
54
+ CPython 3.4.1\n Slash | Slash HEAD\n x86 Assembly | NASM 2.07\n\n== Example:\n\nIt's
55
+ this simple:\n\n result = EvalIn.call 'puts \"example\"', language: \"ruby/mri-2.1\"\n
56
+ \ result.output # returns \"example\\n\"\n\n"
70
57
  email:
71
58
  - josh.cheek@gmail.com
72
59
  executables: []
73
60
  extensions: []
74
61
  extra_rdoc_files: []
75
62
  files:
76
- - ".gitignore"
77
- - ".travis.yml"
63
+ - .gitignore
64
+ - .travis.yml
78
65
  - Gemfile
79
66
  - Readme.md
80
67
  - eval_in.gemspec
@@ -84,26 +71,27 @@ files:
84
71
  homepage: https://github.com/JoshCheek/eval_in
85
72
  licenses:
86
73
  - WTFPL
87
- metadata: {}
88
74
  post_install_message:
89
75
  rdoc_options: []
90
76
  require_paths:
91
77
  - lib
92
78
  required_ruby_version: !ruby/object:Gem::Requirement
79
+ none: false
93
80
  requirements:
94
- - - ">="
81
+ - - ! '>='
95
82
  - !ruby/object:Gem::Version
96
83
  version: '0'
97
84
  required_rubygems_version: !ruby/object:Gem::Requirement
85
+ none: false
98
86
  requirements:
99
- - - ">="
87
+ - - ! '>='
100
88
  - !ruby/object:Gem::Version
101
89
  version: '0'
102
90
  requirements: []
103
91
  rubyforge_project:
104
- rubygems_version: 2.4.1
92
+ rubygems_version: 1.8.23.2
105
93
  signing_key:
106
- specification_version: 4
94
+ specification_version: 3
107
95
  summary: Evaluates code (Ruby and others) safely by sending it to https://eval.in
108
96
  test_files:
109
97
  - spec/eval_in_spec.rb
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 8331a9a20d6f485a925ca9e29ff4daf3c5beebad
4
- data.tar.gz: 4c62d600cddd2acf41608da7832a2aa268a5a05e
5
- SHA512:
6
- metadata.gz: fd354b9ded63f728f01eb81b37952ae8ba97e2ceae8dd7b1d6e7cb76e06eb0d6eb2395ff74902e71f76497ddf470cf0b4dc49331c0153a2ff2f59aeb9ab9dadd
7
- data.tar.gz: 0f15ac725abf2c871d3e50bc08244fbc6a2b8c8173bcdeb068ab4c4c7ed99ebeb53e1f3db0c00e11ab38a07bca5d3cddb142679b906086e76ab6654efa4eaf2c