pycall_thread 0.1.0 → 0.1.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -1
- data/Gemfile +1 -5
- data/Gemfile.lock +1 -5
- data/examples/puma/Gemfile +4 -0
- data/examples/puma/Gemfile.lock +19 -0
- data/examples/puma/README.md +10 -0
- data/examples/puma/app.rb +2 -2
- data/lib/pycall_thread/version.rb +1 -1
- data/lib/pycall_thread.rb +36 -30
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb8af01c4091f60fbf0e3255b487817e6779b18d4f3dc1c449f303cea75094d4
|
4
|
+
data.tar.gz: a8099eecf60897ccc436d5662be887f4ed4641fa1fa655af374b0d322cb64406
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 453798c6771820f009dfefb8ffde48039ca4924df3de24af4a6fffb0a07906cb253c4272006a31072b4e310dae0513a8ca60fd04760d2f8e93ac96480d9d80c5
|
7
|
+
data.tar.gz: 708877b2fbdb55043ed13b84ecbd3ebe6b7c22b9b73b7f074a7435f3294e8762c626aef61695c912a79568672b016b1fa1e7679635db2233ee89b8bdebb45bb6
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
@@ -9,11 +9,7 @@ gem "rake", "~> 13.0"
|
|
9
9
|
gem "minitest", "~> 5.0"
|
10
10
|
gem "rubocop", "~> 1.21"
|
11
11
|
|
12
|
-
|
13
|
-
# Include Puma for testing examples:
|
14
|
-
gem 'puma', '~> 6.4.1'
|
15
|
-
|
16
|
-
# To use the local path, you must also run things with:
|
12
|
+
# To use the local pycall, you must also run things with e.g.:
|
17
13
|
# bundle exec ruby -I/Users/seth/src/pycall.rb/ext/pycall
|
18
14
|
#
|
19
15
|
# gem 'pycall', path: '/Users/seth/src/pycall.rb', require: false
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pycall_thread (0.1.
|
4
|
+
pycall_thread (0.1.1)
|
5
5
|
pycall
|
6
6
|
|
7
7
|
GEM
|
@@ -11,13 +11,10 @@ GEM
|
|
11
11
|
json (2.7.2)
|
12
12
|
language_server-protocol (3.17.0.3)
|
13
13
|
minitest (5.24.1)
|
14
|
-
nio4r (2.7.3)
|
15
14
|
parallel (1.26.0)
|
16
15
|
parser (3.3.4.2)
|
17
16
|
ast (~> 2.4.1)
|
18
17
|
racc
|
19
|
-
puma (6.4.2)
|
20
|
-
nio4r (~> 2.0)
|
21
18
|
pycall (1.5.2)
|
22
19
|
racc (1.8.1)
|
23
20
|
rainbow (3.1.1)
|
@@ -47,7 +44,6 @@ PLATFORMS
|
|
47
44
|
|
48
45
|
DEPENDENCIES
|
49
46
|
minitest (~> 5.0)
|
50
|
-
puma (~> 6.4.1)
|
51
47
|
pycall_thread!
|
52
48
|
rake (~> 13.0)
|
53
49
|
rubocop (~> 1.21)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
nio4r (2.7.3)
|
5
|
+
puma (6.4.2)
|
6
|
+
nio4r (~> 2.0)
|
7
|
+
pycall (1.5.2)
|
8
|
+
pycall_thread (0.1.0)
|
9
|
+
pycall
|
10
|
+
|
11
|
+
PLATFORMS
|
12
|
+
arm64-darwin-23
|
13
|
+
|
14
|
+
DEPENDENCIES
|
15
|
+
puma
|
16
|
+
pycall_thread
|
17
|
+
|
18
|
+
BUNDLED WITH
|
19
|
+
2.2.33
|
data/examples/puma/app.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require 'pycall_thread'
|
2
2
|
|
3
3
|
PyCallThread.init do
|
4
4
|
# Setup our local venv (using pdm, in .venv)
|
@@ -17,7 +17,7 @@ class App
|
|
17
17
|
winequality = PyCallThread.run do
|
18
18
|
pandas = PyCall.import_module('pandas')
|
19
19
|
data = pandas.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv', sep: ';')
|
20
|
-
data.
|
20
|
+
data.to_json()
|
21
21
|
end
|
22
22
|
|
23
23
|
[200, { 'Content-Type' => 'text/html' }, [winequality]]
|
data/lib/pycall_thread.rb
CHANGED
@@ -1,30 +1,40 @@
|
|
1
|
+
# Provides a way to run PyCall code from multiple threads, see
|
2
|
+
# PyCallThread.init and PyCallThread.run for more information.
|
1
3
|
module PyCallThread
|
2
4
|
@queue = Queue.new
|
3
5
|
|
4
|
-
VALID_UNSAFE_RETURN_VALUES = [
|
6
|
+
VALID_UNSAFE_RETURN_VALUES = %i[allow error warn].freeze
|
5
7
|
|
6
8
|
def self.init(unsafe_return: :error, &require_pycall_block)
|
7
|
-
|
8
|
-
raise "PyCall::LibPython already exists: PyCall can't have been initialized already" if defined?(PyCall::LibPython)
|
9
|
+
raise ArgumentError, "Invalid value for unsafe_return: #{unsafe_return}. Must be one of: #{VALID_UNSAFE_RETURN_VALUES.join(", ")}" unless VALID_UNSAFE_RETURN_VALUES.include?(unsafe_return)
|
9
10
|
|
10
|
-
@
|
11
|
+
@unsafe_return = unsafe_return
|
11
12
|
|
12
|
-
if VALID_UNSAFE_RETURN_VALUES.include?(unsafe_return)
|
13
|
-
@unsafe_return = unsafe_return
|
14
|
-
else
|
15
|
-
raise ArgumentError, "Invalid value for unsafe_return: #{unsafe_return}. Must be one of: #{VALID_UNSAFE_RETURN_VALUES.join(', ')}"
|
16
|
-
end
|
17
|
-
|
18
13
|
# Start the thread we will use to run code invoked with PyCallThread.run
|
14
|
+
@py_thread = Thread.new { pycall_thread_loop }
|
15
|
+
|
19
16
|
# If we've been passed a require_pycall_block, use that to require 'pycall'
|
20
17
|
# instead of doing it directly.
|
21
|
-
|
18
|
+
require_pycall(&require_pycall_block)
|
22
19
|
|
23
|
-
at_exit
|
24
|
-
stop_pycall_thread
|
25
|
-
end
|
20
|
+
at_exit { stop_pycall_thread }
|
26
21
|
|
27
|
-
|
22
|
+
@initialized = true
|
23
|
+
end
|
24
|
+
|
25
|
+
def require_pycall(&require_pycall_block)
|
26
|
+
# Only safe to use PyCallThread if PyCall hasn't already been loaded
|
27
|
+
raise "PyCall::LibPython already exists: PyCall can't have been initialized already" if defined?(PyCall::LibPython)
|
28
|
+
|
29
|
+
run do
|
30
|
+
# require 'pycall' or run a user-defined block that should do the same
|
31
|
+
if require_pycall_block
|
32
|
+
require_pycall_block.call
|
33
|
+
else
|
34
|
+
require "pycall"
|
35
|
+
end
|
36
|
+
nil
|
37
|
+
end
|
28
38
|
end
|
29
39
|
|
30
40
|
# Runs &block on the PyCall thread, and returns the result
|
@@ -32,16 +42,18 @@ module PyCallThread
|
|
32
42
|
init unless @initialized
|
33
43
|
|
34
44
|
result_queue = Queue.new
|
35
|
-
@queue <<
|
45
|
+
@queue << lambda {
|
36
46
|
begin
|
37
47
|
result_queue << { retval: block.call }
|
38
|
-
rescue => e
|
48
|
+
rescue StandardError => e
|
39
49
|
result_queue << { exception: e }
|
40
50
|
end
|
41
|
-
|
51
|
+
}
|
42
52
|
|
43
|
-
|
53
|
+
run_result(result_queue.pop)
|
54
|
+
end
|
44
55
|
|
56
|
+
def self.run_result
|
45
57
|
if result[:exception]
|
46
58
|
raise result[:exception]
|
47
59
|
elsif python_object?(result[:retval])
|
@@ -62,21 +74,15 @@ module PyCallThread
|
|
62
74
|
@py_thread.join
|
63
75
|
end
|
64
76
|
|
65
|
-
def self.pycall_thread_loop
|
77
|
+
def self.pycall_thread_loop
|
66
78
|
Thread.current.name = "pycall"
|
67
79
|
|
68
|
-
# require 'pycall' or run a user-defined block that should do the same
|
69
|
-
if require_pycall_block
|
70
|
-
require_pycall_block.call
|
71
|
-
else
|
72
|
-
require 'pycall'
|
73
|
-
end
|
74
|
-
|
75
80
|
loop do
|
76
81
|
block = @queue.pop
|
77
82
|
break if block == :stop
|
83
|
+
|
78
84
|
block.call
|
79
|
-
rescue => e
|
85
|
+
rescue StandardError => e
|
80
86
|
puts "pycall_thread_loop(): exception in pycall_thread_loop #{e}"
|
81
87
|
puts e.backtrace.join("\n")
|
82
88
|
end
|
@@ -93,7 +99,7 @@ module PyCallThread
|
|
93
99
|
PyCall::PyModuleWrapper,
|
94
100
|
PyCall::PyObjectWrapper,
|
95
101
|
PyCall::PyTypeObjectWrapper,
|
96
|
-
PyCall::PyPtr
|
102
|
+
PyCall::PyPtr
|
97
103
|
].any? { |kind| obj.is_a?(kind) }
|
98
104
|
end
|
99
|
-
end
|
105
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pycall_thread
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Seth Nickell
|
@@ -41,6 +41,9 @@ files:
|
|
41
41
|
- Rakefile
|
42
42
|
- bin/console
|
43
43
|
- bin/setup
|
44
|
+
- examples/puma/Gemfile
|
45
|
+
- examples/puma/Gemfile.lock
|
46
|
+
- examples/puma/README.md
|
44
47
|
- examples/puma/app.rb
|
45
48
|
- examples/puma/config.ru
|
46
49
|
- examples/puma/start_puma.sh
|