piston_sdk 0.1.0 → 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.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +34 -0
- data/README.md +1 -1
- data/lib/piston_sdk/version.rb +1 -1
- data/lib/piston_sdk.rb +178 -62
- data/sorbet/config +4 -0
- data/sorbet/rbi/annotations/.gitattributes +1 -0
- data/sorbet/rbi/annotations/rainbow.rbi +269 -0
- data/sorbet/rbi/gems/.gitattributes +1 -0
- data/sorbet/rbi/gems/ast@2.4.3.rbi +585 -0
- data/sorbet/rbi/gems/benchmark@0.4.1.rbi +619 -0
- data/sorbet/rbi/gems/date@3.4.1.rbi +75 -0
- data/sorbet/rbi/gems/diff-lcs@1.6.2.rbi +1134 -0
- data/sorbet/rbi/gems/erb@5.0.2.rbi +878 -0
- data/sorbet/rbi/gems/erubi@1.13.1.rbi +155 -0
- data/sorbet/rbi/gems/io-console@0.8.1.rbi +9 -0
- data/sorbet/rbi/gems/json@2.14.1.rbi +2101 -0
- data/sorbet/rbi/gems/language_server-protocol@3.17.0.5.rbi +9 -0
- data/sorbet/rbi/gems/lint_roller@1.1.0.rbi +86 -0
- data/sorbet/rbi/gems/logger@1.7.0.rbi +963 -0
- data/sorbet/rbi/gems/netrc@0.11.0.rbi +159 -0
- data/sorbet/rbi/gems/parallel@1.27.0.rbi +291 -0
- data/sorbet/rbi/gems/parser@3.3.9.0.rbi +5535 -0
- data/sorbet/rbi/gems/pp@0.6.2.rbi +368 -0
- data/sorbet/rbi/gems/prettyprint@0.2.0.rbi +477 -0
- data/sorbet/rbi/gems/prism@1.5.1.rbi +42049 -0
- data/sorbet/rbi/gems/psych@5.2.6.rbi +2469 -0
- data/sorbet/rbi/gems/racc@1.8.1.rbi +160 -0
- data/sorbet/rbi/gems/rainbow@3.1.1.rbi +403 -0
- data/sorbet/rbi/gems/rake@13.3.0.rbi +3036 -0
- data/sorbet/rbi/gems/rbi@0.3.6.rbi +6893 -0
- data/sorbet/rbi/gems/rbs@3.9.5.rbi +6978 -0
- data/sorbet/rbi/gems/rdoc@6.14.2.rbi +12688 -0
- data/sorbet/rbi/gems/regexp_parser@2.11.3.rbi +3845 -0
- data/sorbet/rbi/gems/reline@0.6.2.rbi +2441 -0
- data/sorbet/rbi/gems/rexml@3.4.4.rbi +5285 -0
- data/sorbet/rbi/gems/rspec-core@3.13.5.rbi +11103 -0
- data/sorbet/rbi/gems/rspec-expectations@3.13.5.rbi +8189 -0
- data/sorbet/rbi/gems/rspec-mocks@3.13.5.rbi +5350 -0
- data/sorbet/rbi/gems/rspec-support@3.13.6.rbi +1627 -0
- data/sorbet/rbi/gems/rspec@3.13.1.rbi +83 -0
- data/sorbet/rbi/gems/rubocop-ast@1.46.0.rbi +7734 -0
- data/sorbet/rbi/gems/rubocop@1.80.2.rbi +63356 -0
- data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1318 -0
- data/sorbet/rbi/gems/spoom@1.6.3.rbi +6985 -0
- data/sorbet/rbi/gems/stringio@3.1.7.rbi +9 -0
- data/sorbet/rbi/gems/tapioca@0.16.11.rbi +3628 -0
- data/sorbet/rbi/gems/thor@1.4.0.rbi +4399 -0
- data/sorbet/rbi/gems/unicode-display_width@3.2.0.rbi +132 -0
- data/sorbet/rbi/gems/unicode-emoji@4.1.0.rbi +251 -0
- data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
- data/sorbet/rbi/gems/yard@0.9.37.rbi +18379 -0
- data/sorbet/tapioca/config.yml +13 -0
- data/sorbet/tapioca/require.rb +4 -0
- metadata +51 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a36996117e89c98c36fa3479f6789dbc9a1d160c729bcb85660e2dff55064eb0
|
4
|
+
data.tar.gz: b4a2ab4d363581f6235c7ac055db053ef474be9640dc5022904eefb5d160efd6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 663cdbfc6dbf27f92630b907e0920dcd934caee502e67d796daf713cb3156f65c6359aa024a2a42be4f0d1b05de8f76dc99206e477d0aa9895d9302963cbfddd
|
7
|
+
data.tar.gz: d55471bfac793667c767f74afa02fcd12bb18fcaf51b00172fbbc1b5546732106763ed2fb15d4252f52bbe87fa2f21ec44ecbbd474fa618c6116718f449cf01d
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
|
+
|
7
|
+
## [Unreleased]
|
8
|
+
|
9
|
+
### Added
|
10
|
+
|
11
|
+
### Changed
|
12
|
+
|
13
|
+
### Deprecated
|
14
|
+
|
15
|
+
### Removed
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
|
19
|
+
### Security
|
20
|
+
|
21
|
+
## 0.2.0 2025-09-28
|
22
|
+
|
23
|
+
### Added
|
24
|
+
|
25
|
+
- [Sorbet](https://sorbet.org/) type assertions.
|
26
|
+
- Support for platforms `x86_64-darwin-23` and `x86_64-linux`
|
27
|
+
|
28
|
+
### Changed
|
29
|
+
|
30
|
+
- Improve documentation comments.
|
31
|
+
|
32
|
+
## 0.1.0 - 2025-09-21
|
33
|
+
|
34
|
+
This is the first release of *piston_sdk*! :tada:
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
|
13
13
|
<div align="center">
|
14
14
|
|
15
|
-
[](https://github.com/alvii147/piston-ruby-sdk/actions) [](https://github.com/alvii147/piston-ruby-sdk/blob/main/LICENSE)
|
15
|
+
[](https://badge.fury.io/rb/piston_sdk) [](https://github.com/alvii147/piston-ruby-sdk/actions) [](https://github.com/alvii147/piston-ruby-sdk/blob/main/LICENSE)
|
16
16
|
|
17
17
|
</div>
|
18
18
|
|
data/lib/piston_sdk/version.rb
CHANGED
data/lib/piston_sdk.rb
CHANGED
@@ -1,78 +1,155 @@
|
|
1
|
+
# typed: true
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require "net/http"
|
4
5
|
require "json"
|
6
|
+
require "sorbet-runtime"
|
5
7
|
require_relative "piston_sdk/version"
|
6
8
|
|
7
9
|
# A minimal Ruby gem for using the [Piston API](https://github.com/engineer-man/piston).
|
8
10
|
module PistonSDK
|
9
11
|
# Data representation of a Piston runtime.
|
10
12
|
class Runtime
|
11
|
-
|
13
|
+
extend T::Sig
|
14
|
+
|
15
|
+
sig { returns(String) }
|
16
|
+
attr_reader :language
|
17
|
+
|
18
|
+
sig { returns(String) }
|
19
|
+
attr_reader :version
|
20
|
+
|
21
|
+
sig { returns(T::Array[String]) }
|
22
|
+
attr_reader :aliases
|
23
|
+
|
24
|
+
sig { returns(T.nilable(String)) }
|
25
|
+
attr_reader :runtime
|
12
26
|
|
13
27
|
# Create a new Piston runtime.
|
14
28
|
#
|
15
|
-
# @param data [Hash] JSON data
|
29
|
+
# @param data [Hash] JSON data
|
30
|
+
sig { params(data: T::Hash[String, T.untyped]).void }
|
16
31
|
def initialize(data)
|
17
|
-
@language = data["language"]
|
18
|
-
@version = data["version"]
|
19
|
-
@aliases = data["aliases"]
|
20
|
-
@runtime = data["runtime"]
|
32
|
+
@language = T.let(data["language"], String)
|
33
|
+
@version = T.let(data["version"], String)
|
34
|
+
@aliases = T.let(data["aliases"], T::Array[String])
|
35
|
+
@runtime = T.let(data["runtime"], T.nilable(String))
|
21
36
|
end
|
22
37
|
end
|
23
38
|
|
24
39
|
# Data representation of Piston execution step details.
|
25
40
|
class ExecutionStepDetails
|
26
|
-
|
41
|
+
extend T::Sig
|
42
|
+
|
43
|
+
sig { returns(String) }
|
44
|
+
attr_reader :stdout
|
45
|
+
|
46
|
+
sig { returns(String) }
|
47
|
+
attr_reader :stderr
|
48
|
+
|
49
|
+
sig { returns(String) }
|
50
|
+
attr_reader :output
|
51
|
+
|
52
|
+
sig { returns(T.nilable(Integer)) }
|
53
|
+
attr_reader :code
|
54
|
+
|
55
|
+
sig { returns(T.nilable(String)) }
|
56
|
+
attr_reader :signal
|
57
|
+
|
58
|
+
sig { returns(T.nilable(String)) }
|
59
|
+
attr_reader :message
|
60
|
+
|
61
|
+
sig { returns(T.nilable(String)) }
|
62
|
+
attr_reader :status
|
63
|
+
|
64
|
+
sig { returns(T.nilable(Integer)) }
|
65
|
+
attr_reader :cpu_time
|
66
|
+
|
67
|
+
sig { returns(T.nilable(Integer)) }
|
68
|
+
attr_reader :wall_time
|
69
|
+
|
70
|
+
sig { returns(T.nilable(Integer)) }
|
71
|
+
attr_reader :memory
|
27
72
|
|
28
73
|
# Create new Piston execution step details.
|
29
74
|
#
|
30
|
-
# @param data [Hash] JSON data
|
75
|
+
# @param data [Hash] JSON data
|
76
|
+
sig { params(data: T::Hash[String, T.untyped]).void }
|
31
77
|
def initialize(data)
|
32
|
-
@stdout = data["stdout"]
|
33
|
-
@stderr = data["stderr"]
|
34
|
-
@output = data["output"]
|
35
|
-
@code = data["code"]
|
36
|
-
@signal = data["signal"]
|
37
|
-
@message = data["message"]
|
38
|
-
@status = data["status"]
|
39
|
-
@cpu_time = data["cpu_time"]
|
40
|
-
@wall_time = data["wall_time"]
|
41
|
-
@memory = data["memory"]
|
78
|
+
@stdout = T.let(data["stdout"], String)
|
79
|
+
@stderr = T.let(data["stderr"], String)
|
80
|
+
@output = T.let(data["output"], String)
|
81
|
+
@code = T.let(data["code"], T.nilable(Integer))
|
82
|
+
@signal = T.let(data["signal"], T.nilable(String))
|
83
|
+
@message = T.let(data["message"], T.nilable(String))
|
84
|
+
@status = T.let(data["status"], T.nilable(String))
|
85
|
+
@cpu_time = T.let(data["cpu_time"], T.nilable(Integer))
|
86
|
+
@wall_time = T.let(data["wall_time"], T.nilable(Integer))
|
87
|
+
@memory = T.let(data["memory"], T.nilable(Integer))
|
42
88
|
end
|
43
89
|
end
|
44
90
|
|
45
91
|
# Data representation of Piston execution results.
|
46
92
|
class ExecutionResults
|
47
|
-
|
93
|
+
extend T::Sig
|
94
|
+
|
95
|
+
sig { returns(String) }
|
96
|
+
attr_reader :language
|
97
|
+
|
98
|
+
sig { returns(String) }
|
99
|
+
attr_reader :version
|
100
|
+
|
101
|
+
sig { returns(ExecutionStepDetails) }
|
102
|
+
attr_reader :run
|
103
|
+
|
104
|
+
sig { returns(T.nilable(ExecutionStepDetails)) }
|
105
|
+
attr_reader :compile
|
48
106
|
|
49
107
|
# Create new Piston execution results.
|
50
108
|
#
|
51
|
-
# @param data [Hash] JSON data
|
109
|
+
# @param data [Hash] JSON data
|
110
|
+
sig { params(data: T::Hash[String, T.untyped]).void }
|
52
111
|
def initialize(data)
|
53
|
-
@language = data["language"]
|
54
|
-
@version = data["version"]
|
55
|
-
@run = ExecutionStepDetails.new(data["run"])
|
56
|
-
@compile =
|
112
|
+
@language = T.let(data["language"], String)
|
113
|
+
@version = T.let(data["version"], String)
|
114
|
+
@run = T.let(ExecutionStepDetails.new(data["run"]), ExecutionStepDetails)
|
115
|
+
@compile = T.let(
|
116
|
+
data["compile"] ? ExecutionStepDetails.new(data["compile"]) : nil,
|
117
|
+
T.nilable(ExecutionStepDetails)
|
118
|
+
)
|
57
119
|
end
|
58
120
|
end
|
59
121
|
|
60
122
|
# HTTP client for the Piston API.
|
61
123
|
class Client
|
124
|
+
extend T::Sig
|
125
|
+
|
62
126
|
# Create a new client.
|
63
127
|
#
|
64
|
-
# @param base_url [String] Base URL for API
|
128
|
+
# @param base_url [String] Base URL for API
|
129
|
+
# @param retries [Integer] Number of automatic retries to perform when rate limit is reached
|
65
130
|
# @param compile_timeout [Integer, nil] The maximum wall-time allowed for the compile stage to finish before bailing
|
66
|
-
# out in milliseconds
|
131
|
+
# out in milliseconds
|
67
132
|
# @param run_timeout [Integer, nil] The maximum wall-time allowed for the run stage to finish before bailing out in
|
68
|
-
# milliseconds
|
133
|
+
# milliseconds
|
69
134
|
# @param compile_cpu_time [Integer, nil] The maximum CPU-time allowed for the compile stage to finish before bailing
|
70
|
-
# out in milliseconds
|
135
|
+
# out in milliseconds
|
71
136
|
# @param run_cpu_time [Integer, nil] The maximum CPU-time allowed for the run stage to finish before bailing out in
|
72
|
-
# milliseconds
|
137
|
+
# milliseconds
|
73
138
|
# @param compile_memory_limit [Integer, nil] The maximum amount of memory the compile stage is allowed to use in
|
74
|
-
# bytes
|
75
|
-
# @param run_memory_limit [Integer, nil] The maximum amount of memory the run stage is allowed to use in bytes
|
139
|
+
# bytes
|
140
|
+
# @param run_memory_limit [Integer, nil] The maximum amount of memory the run stage is allowed to use in bytes
|
141
|
+
sig do
|
142
|
+
params(
|
143
|
+
base_url: String,
|
144
|
+
retries: Integer,
|
145
|
+
compile_timeout: T.nilable(Integer),
|
146
|
+
run_timeout: T.nilable(Integer),
|
147
|
+
compile_cpu_time: T.nilable(Integer),
|
148
|
+
run_cpu_time: T.nilable(Integer),
|
149
|
+
compile_memory_limit: T.nilable(Integer),
|
150
|
+
run_memory_limit: T.nilable(Integer)
|
151
|
+
).void
|
152
|
+
end
|
76
153
|
def initialize(
|
77
154
|
base_url: "https://emkc.org/api/v2/piston",
|
78
155
|
retries: 3,
|
@@ -83,32 +160,48 @@ module PistonSDK
|
|
83
160
|
compile_memory_limit: nil,
|
84
161
|
run_memory_limit: nil
|
85
162
|
)
|
86
|
-
@uri = URI(base_url)
|
87
|
-
@retries = retries
|
88
|
-
@compile_timeout = compile_timeout
|
89
|
-
@run_timeout = run_timeout
|
90
|
-
@compile_cpu_time = compile_cpu_time
|
91
|
-
@run_cpu_time = run_cpu_time
|
92
|
-
@compile_memory_limit = compile_memory_limit
|
93
|
-
@run_memory_limit = run_memory_limit
|
94
|
-
@files = []
|
95
|
-
|
96
|
-
@http = Net::HTTP.new(@uri.host, @uri.port)
|
163
|
+
@uri = T.let(URI(base_url), URI::Generic)
|
164
|
+
@retries = T.let(retries, Integer)
|
165
|
+
@compile_timeout = T.let(compile_timeout, T.nilable(Integer))
|
166
|
+
@run_timeout = T.let(run_timeout, T.nilable(Integer))
|
167
|
+
@compile_cpu_time = T.let(compile_cpu_time, T.nilable(Integer))
|
168
|
+
@run_cpu_time = T.let(run_cpu_time, T.nilable(Integer))
|
169
|
+
@compile_memory_limit = T.let(compile_memory_limit, T.nilable(Integer))
|
170
|
+
@run_memory_limit = T.let(run_memory_limit, T.nilable(Integer))
|
171
|
+
@files = T.let([], T::Array[T::Hash[Symbol, String]])
|
172
|
+
|
173
|
+
@http = T.let(Net::HTTP.new(@uri.host, @uri.port), Net::HTTP)
|
97
174
|
@http.use_ssl = true
|
98
175
|
|
99
|
-
@method_classes =
|
100
|
-
|
101
|
-
|
176
|
+
@method_classes = T.let(
|
177
|
+
{
|
178
|
+
get: Net::HTTP::Get,
|
179
|
+
post: Net::HTTP::Post
|
180
|
+
},
|
181
|
+
T::Hash[Symbol, T.class_of(Net::HTTPRequest)]
|
182
|
+
)
|
102
183
|
end
|
103
184
|
|
104
185
|
# Perform raw HTTP request using exponential backoff on retries.
|
105
186
|
#
|
106
|
-
# @param method [Symbol] HTTP method
|
107
|
-
# @param path [String] URL Path
|
187
|
+
# @param method [Symbol] HTTP method
|
188
|
+
# @param path [String] URL Path
|
108
189
|
# @param body [Hash, nil] Optional request body
|
109
|
-
# @return [Hash, Array] JSON response
|
190
|
+
# @return [Hash, Array] JSON response
|
191
|
+
sig do
|
192
|
+
params(
|
193
|
+
method: Symbol,
|
194
|
+
path: String,
|
195
|
+
body: T.nilable(T::Hash[Symbol, T.untyped])
|
196
|
+
).returns(
|
197
|
+
T.any(
|
198
|
+
T::Hash[T.untyped, T.untyped],
|
199
|
+
T::Array[T.untyped]
|
200
|
+
)
|
201
|
+
)
|
202
|
+
end
|
110
203
|
def request(method: :get, path: "", body: nil)
|
111
|
-
req = @method_classes[method].new("#{@uri}#{path}")
|
204
|
+
req = T.must(@method_classes[method]).new("#{@uri}#{path}")
|
112
205
|
req["Content-Type"] = "application/json"
|
113
206
|
req.body = body.to_json unless body.nil?
|
114
207
|
res = @http.request(req)
|
@@ -118,20 +211,29 @@ module PistonSDK
|
|
118
211
|
|
119
212
|
case res
|
120
213
|
when Net::HTTPOK
|
121
|
-
return JSON.parse(res.body)
|
214
|
+
return JSON.parse(res.body || "{}")
|
122
215
|
when Net::HTTPTooManyRequests
|
123
216
|
sleep 2**attempt
|
124
217
|
else
|
125
218
|
raise "Request failed with status code #{res.code}, #{res.body}"
|
126
219
|
end
|
127
220
|
end
|
221
|
+
|
222
|
+
raise "Request failed due to rate limits after too many attempts"
|
128
223
|
end
|
129
224
|
|
130
225
|
# Add file to be sent to Piston for execution.
|
131
226
|
#
|
132
|
-
# @param content [String] Content of the files to upload
|
133
|
-
# @param name [String, nil] Name of the file to upload
|
134
|
-
# @param encoding [String, nil] Encoding scheme used for the file content
|
227
|
+
# @param content [String] Content of the files to upload
|
228
|
+
# @param name [String, nil] Name of the file to upload
|
229
|
+
# @param encoding [String, nil] Encoding scheme used for the file content
|
230
|
+
sig do
|
231
|
+
params(
|
232
|
+
content: String,
|
233
|
+
name: T.nilable(String),
|
234
|
+
encoding: T.nilable(String)
|
235
|
+
).void
|
236
|
+
end
|
135
237
|
def add_file(content:, name: nil, encoding: nil)
|
136
238
|
file = {
|
137
239
|
name: name,
|
@@ -142,25 +244,37 @@ module PistonSDK
|
|
142
244
|
@files << file
|
143
245
|
end
|
144
246
|
|
145
|
-
# Clear all files
|
247
|
+
# Clear all files
|
248
|
+
sig { void }
|
146
249
|
def clear_files
|
147
250
|
@files.clear
|
148
251
|
end
|
149
252
|
|
150
253
|
# Get supported languages along with the current version and aliases.
|
151
254
|
#
|
152
|
-
# @return [Array<Runtime>]
|
255
|
+
# @return [Array<Runtime>] List of supported runtimes
|
256
|
+
sig { returns(T::Array[Runtime]) }
|
153
257
|
def runtimes
|
154
|
-
request(method: :get, path: "/runtimes").map
|
258
|
+
request(method: :get, path: "/runtimes").map do |data|
|
259
|
+
Runtime.new(T.cast(data, T::Hash[String, T.untyped]))
|
260
|
+
end
|
155
261
|
end
|
156
262
|
|
157
263
|
# Execute code for a given language and version using the added files.
|
158
264
|
#
|
159
|
-
# @param language [String] Language to use for execution
|
160
|
-
# @param version [String] Version of the language to use for execution
|
161
|
-
# @param stdin [String, nil] Text to pass as stdin to the program
|
162
|
-
# @param args [Array<String>] Arguments to pass to the program
|
163
|
-
# @return [ExecutionResults] Execution results
|
265
|
+
# @param language [String] Language to use for execution
|
266
|
+
# @param version [String] Version of the language to use for execution
|
267
|
+
# @param stdin [String, nil] Text to pass as stdin to the program
|
268
|
+
# @param args [Array<String>] Arguments to pass to the program
|
269
|
+
# @return [ExecutionResults] Execution results
|
270
|
+
sig do
|
271
|
+
params(
|
272
|
+
language: String,
|
273
|
+
version: String,
|
274
|
+
stdin: T.nilable(String),
|
275
|
+
args: T.nilable(T::Array[String])
|
276
|
+
).returns(ExecutionResults)
|
277
|
+
end
|
164
278
|
def execute(language:, version:, stdin: nil, args: nil)
|
165
279
|
body = {
|
166
280
|
language: language,
|
@@ -176,7 +290,9 @@ module PistonSDK
|
|
176
290
|
run_memory_limit: @run_memory_limit
|
177
291
|
}.compact
|
178
292
|
|
179
|
-
ExecutionResults.new(
|
293
|
+
ExecutionResults.new(
|
294
|
+
T.cast(request(method: :post, path: "/execute", body: body), T::Hash[String, T.untyped])
|
295
|
+
)
|
180
296
|
end
|
181
297
|
|
182
298
|
private :request
|
data/sorbet/config
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
**/*.rbi linguist-vendored=true
|