pycall 1.0.3 → 1.3.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 +5 -5
- data/.github/workflows/ci.yml +67 -0
- data/.travis.yml +46 -21
- data/CHANGES.md +62 -0
- data/README.md +66 -2
- data/Rakefile +2 -0
- data/appveyor.yml +8 -54
- data/ci/travis_install.sh +30 -9
- data/examples/classifier_comparison.rb +1 -1
- data/examples/hist.rb +1 -1
- data/examples/notebooks/classifier_comparison.ipynb +1 -1
- data/ext/pycall/libpython.c +12 -1
- data/ext/pycall/pycall.c +149 -5
- data/ext/pycall/pycall.h +23 -0
- data/ext/pycall/pycall_internal.h +35 -1
- data/ext/pycall/ruby_wrapper.c +171 -79
- data/ext/pycall/thread.c +36 -0
- data/images/pycallrb_logo.png +0 -0
- data/images/pycallrb_logo_200.png +0 -0
- data/lib/pycall.rb +10 -0
- data/lib/pycall/dict.rb +2 -2
- data/lib/pycall/iruby_helper.rb +1 -1
- data/lib/pycall/libpython/finder.rb +23 -22
- data/lib/pycall/list.rb +2 -2
- data/lib/pycall/pymodule_wrapper.rb +46 -0
- data/lib/pycall/pyobject_wrapper.rb +4 -32
- data/lib/pycall/python/investigator.py +0 -4
- data/lib/pycall/pytypeobject_wrapper.rb +19 -0
- data/lib/pycall/version.rb +7 -1
- data/pycall.gemspec +11 -4
- metadata +21 -18
- data/lib/pycall/conversion.rb +0 -173
- data/lib/pycall/tuple.rb +0 -46
data/ext/pycall/thread.c
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#include "pycall_internal.h"
|
2
|
+
|
3
|
+
#if defined(PYCALL_THREAD_WIN32)
|
4
|
+
int pycall_tls_create(pycall_tls_key *tls_key)
|
5
|
+
{
|
6
|
+
*tls_key = TlsAlloc();
|
7
|
+
return *tls_key == TLS_OUT_OF_INDEXES;
|
8
|
+
}
|
9
|
+
|
10
|
+
void *pycall_tls_get(pycall_tls_key tls_key)
|
11
|
+
{
|
12
|
+
return TlsGetValue(tls_key);
|
13
|
+
}
|
14
|
+
|
15
|
+
int pycall_tls_set(pycall_tls_key tls_key, void *ptr)
|
16
|
+
{
|
17
|
+
return 0 == TlsSetValue(tls_key, ptr);
|
18
|
+
}
|
19
|
+
#endif
|
20
|
+
|
21
|
+
#if defined(PYCALL_THREAD_PTHREAD)
|
22
|
+
int pycall_tls_create(pycall_tls_key *tls_key)
|
23
|
+
{
|
24
|
+
return pthread_key_create(tls_key, NULL);
|
25
|
+
}
|
26
|
+
|
27
|
+
void *pycall_tls_get(pycall_tls_key tls_key)
|
28
|
+
{
|
29
|
+
return pthread_getspecific(tls_key);
|
30
|
+
}
|
31
|
+
|
32
|
+
int pycall_tls_set(pycall_tls_key tls_key, void *ptr)
|
33
|
+
{
|
34
|
+
return pthread_setspecific(tls_key, ptr);
|
35
|
+
}
|
36
|
+
#endif
|
Binary file
|
Binary file
|
data/lib/pycall.rb
CHANGED
@@ -4,6 +4,7 @@ module PyCall
|
|
4
4
|
require 'pycall/pyerror'
|
5
5
|
require 'pycall/pyobject_wrapper'
|
6
6
|
require 'pycall/pytypeobject_wrapper'
|
7
|
+
require 'pycall/pymodule_wrapper'
|
7
8
|
require 'pycall/init'
|
8
9
|
|
9
10
|
module_function
|
@@ -48,6 +49,15 @@ module PyCall
|
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
52
|
+
def getattr(*args)
|
53
|
+
obj, *rest = args
|
54
|
+
LibPython::Helpers.getattr(obj.__pyptr__, *rest)
|
55
|
+
end
|
56
|
+
|
57
|
+
def hasattr?(obj, name)
|
58
|
+
LibPython::Helpers.hasattr?(obj.__pyptr__, name)
|
59
|
+
end
|
60
|
+
|
51
61
|
def import_module(name)
|
52
62
|
LibPython::Helpers.import_module(name)
|
53
63
|
end
|
data/lib/pycall/dict.rb
CHANGED
data/lib/pycall/iruby_helper.rb
CHANGED
@@ -19,29 +19,26 @@ module PyCall
|
|
19
19
|
LIBSUFFIX = libsuffix || 'so'
|
20
20
|
|
21
21
|
class << self
|
22
|
+
DEFAULT_PYTHON = [
|
23
|
+
-'python3',
|
24
|
+
-'python',
|
25
|
+
].freeze
|
26
|
+
|
27
|
+
def find_python_config(python = nil)
|
28
|
+
python ||= DEFAULT_PYTHON
|
29
|
+
Array(python).each do |python_cmd|
|
30
|
+
begin
|
31
|
+
python_config = investigate_python_config(python_cmd)
|
32
|
+
return [python_cmd, python_config] unless python_config.empty?
|
33
|
+
rescue
|
34
|
+
end
|
35
|
+
end
|
36
|
+
raise ::PyCall::PythonNotFound
|
37
|
+
end
|
38
|
+
|
22
39
|
def find_libpython(python = nil)
|
23
40
|
debug_report("find_libpython(#{python.inspect})")
|
24
|
-
|
25
|
-
begin
|
26
|
-
python_config = investigate_python_config(python)
|
27
|
-
rescue
|
28
|
-
raise ::PyCall::PythonNotFound
|
29
|
-
end
|
30
|
-
else
|
31
|
-
%w[python python3].each do |python_cmd|
|
32
|
-
begin
|
33
|
-
python_config = investigate_python_config(python_cmd)
|
34
|
-
python = python_cmd
|
35
|
-
break
|
36
|
-
rescue
|
37
|
-
raise ::PyCall::PythonNotFound
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
set_PYTHONHOME(python_config)
|
43
|
-
libs = make_libs(python_config)
|
44
|
-
libpaths = make_libpaths(python_config)
|
41
|
+
python, python_config = find_python_config(python)
|
45
42
|
|
46
43
|
# Try LIBPYTHON environment variable first.
|
47
44
|
if (libpython = ENV['LIBPYTHON'])
|
@@ -58,6 +55,9 @@ module PyCall
|
|
58
55
|
end
|
59
56
|
|
60
57
|
# Find libpython (we hope):
|
58
|
+
set_PYTHONHOME(python_config)
|
59
|
+
libs = make_libs(python_config)
|
60
|
+
libpaths = make_libpaths(python_config)
|
61
61
|
multiarch = python_config[:MULTIARCH] || python_config[:multiarch]
|
62
62
|
libs.each do |lib|
|
63
63
|
libpaths.each do |libpath|
|
@@ -101,6 +101,7 @@ module PyCall
|
|
101
101
|
IO.popen(python_env, [python, python_investigator_py], 'r') do |io|
|
102
102
|
{}.tap do |config|
|
103
103
|
io.each_line do |line|
|
104
|
+
next unless line =~ /: /
|
104
105
|
key, value = line.chomp.split(': ', 2)
|
105
106
|
case value
|
106
107
|
when 'True', 'true', 'False', 'false'
|
@@ -119,7 +120,7 @@ module PyCall
|
|
119
120
|
end
|
120
121
|
|
121
122
|
def set_PYTHONHOME(python_config)
|
122
|
-
if !ENV.has_key?('PYTHONHOME')
|
123
|
+
if !ENV.has_key?('PYTHONHOME')
|
123
124
|
case RUBY_PLATFORM
|
124
125
|
when /mingw32/, /cygwin/, /mswin/
|
125
126
|
ENV['PYTHONHOME'] = python_config[:exec_prefix]
|
data/lib/pycall/list.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'pycall/pyobject_wrapper'
|
2
|
+
|
3
|
+
module PyCall
|
4
|
+
module PyModuleWrapper
|
5
|
+
include PyObjectWrapper
|
6
|
+
|
7
|
+
def [](*args)
|
8
|
+
case args[0]
|
9
|
+
when String, Symbol
|
10
|
+
PyCall.getattr(self, args[0])
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module_function
|
18
|
+
|
19
|
+
class WrapperModuleCache < WrapperObjectCache
|
20
|
+
def initialize
|
21
|
+
super(LibPython::API::PyModule_Type)
|
22
|
+
end
|
23
|
+
|
24
|
+
def check_wrapper_object(wrapper_object)
|
25
|
+
unless wrapper_object.kind_of?(Module) && wrapper_object.kind_of?(PyObjectWrapper)
|
26
|
+
raise TypeError, "unexpected type #{wrapper_object.class} (expected Module extended by PyObjectWrapper)"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.instance
|
31
|
+
@instance ||= self.new
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private_constant :WrapperModuleCache
|
36
|
+
|
37
|
+
def wrap_module(pymodptr)
|
38
|
+
check_ismodule(pymodptr)
|
39
|
+
WrapperModuleCache.instance.lookup(pymodptr) do
|
40
|
+
Module.new do |mod|
|
41
|
+
mod.instance_variable_set(:@__pyptr__, pymodptr)
|
42
|
+
mod.extend PyModuleWrapper
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -170,43 +170,15 @@ module PyCall
|
|
170
170
|
|
171
171
|
module_function
|
172
172
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
end
|
177
|
-
|
178
|
-
def check_wrapper_object(wrapper_object)
|
179
|
-
unless wrapper_object.kind_of?(Module) && wrapper_object.kind_of?(PyObjectWrapper)
|
180
|
-
raise TypeError, "unexpected type #{wrapper_object.class} (expected Module extended by PyObjectWrapper)"
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
def self.instance
|
185
|
-
@instance ||= self.new
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
private_constant :WrapperModuleCache
|
190
|
-
|
191
|
-
def wrap_module(pymodptr)
|
192
|
-
check_ismodule(pymodptr)
|
193
|
-
WrapperModuleCache.instance.lookup(pymodptr) do
|
194
|
-
Module.new do |mod|
|
195
|
-
mod.instance_variable_set(:@__pyptr__, pymodptr)
|
196
|
-
mod.extend PyObjectWrapper
|
197
|
-
end
|
198
|
-
end
|
173
|
+
def check_ismodule(pyptr)
|
174
|
+
return if pyptr.kind_of? LibPython::API::PyModule_Type
|
175
|
+
raise TypeError, "PyModule object is required"
|
199
176
|
end
|
200
177
|
|
201
178
|
def check_isclass(pyptr)
|
202
179
|
pyptr = pyptr.__pyptr__ if pyptr.kind_of? PyObjectWrapper
|
203
180
|
return if pyptr.kind_of? LibPython::API::PyType_Type
|
204
|
-
return defined?(LibPython::API::PyClass_Type) && pyptr.kind_of?(LibPython::API::PyClass_Type)
|
181
|
+
return if defined?(LibPython::API::PyClass_Type) && pyptr.kind_of?(LibPython::API::PyClass_Type)
|
205
182
|
raise TypeError, "PyType object is required"
|
206
183
|
end
|
207
|
-
|
208
|
-
def check_ismodule(pyptr)
|
209
|
-
return if pyptr.kind_of? LibPython::API::PyModule_Type
|
210
|
-
raise TypeError, "PyModule object is required"
|
211
|
-
end
|
212
184
|
end
|
@@ -1,12 +1,8 @@
|
|
1
1
|
from distutils.sysconfig import get_config_var
|
2
2
|
import sys
|
3
3
|
|
4
|
-
def conda():
|
5
|
-
return 'conda' in sys.version or 'Continuum' in sys.version
|
6
|
-
|
7
4
|
for var in ('executable', 'exec_prefix', 'prefix'):
|
8
5
|
print(var + ': ' + str(getattr(sys, var)))
|
9
|
-
print('conda: ' + ('true' if conda() else 'false'))
|
10
6
|
print('multiarch: ' + str(getattr(getattr(sys, 'implementation', sys), '_multiarch', None)))
|
11
7
|
for var in ('VERSION', 'INSTSONAME', 'LIBRARY', 'LDLIBRARY', 'LIBDIR', 'PYTHONFRAMEWORKPREFIX', 'MULTIARCH'):
|
12
8
|
print(var + ': ' + str(get_config_var(var)))
|
@@ -49,6 +49,25 @@ module PyCall
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
+
def <(other)
|
53
|
+
case other
|
54
|
+
when self
|
55
|
+
false
|
56
|
+
when PyTypeObjectWrapper
|
57
|
+
__pyptr__ < other.__pyptr__
|
58
|
+
when Class
|
59
|
+
false if other.ancestors.include?(self)
|
60
|
+
when Module
|
61
|
+
if ancestors.include?(other)
|
62
|
+
true
|
63
|
+
elsif other.ancestors.include?(self)
|
64
|
+
false
|
65
|
+
end
|
66
|
+
else
|
67
|
+
raise TypeError, "compared with non class/module"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
52
71
|
private
|
53
72
|
|
54
73
|
def register_python_type_mapping
|
data/lib/pycall/version.rb
CHANGED
data/pycall.gemspec
CHANGED
@@ -5,7 +5,13 @@ require 'pycall/version'
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "pycall"
|
8
|
-
|
8
|
+
version_components = [
|
9
|
+
PyCall::Version::MAJOR.to_s,
|
10
|
+
PyCall::Version::MINOR.to_s,
|
11
|
+
PyCall::Version::MICRO.to_s,
|
12
|
+
PyCall::Version::TAG,
|
13
|
+
]
|
14
|
+
spec.version = version_components.compact.join(".")
|
9
15
|
spec.authors = ["Kenta Murata"]
|
10
16
|
spec.email = ["mrkn@mrkn.jp"]
|
11
17
|
|
@@ -17,6 +23,7 @@ Gem::Specification.new do |spec|
|
|
17
23
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
24
|
case f
|
19
25
|
when %r{^Guardfile}, # NOTE: Skip symlink for Windows
|
26
|
+
%r{^ext/pycall/spec_helper/},
|
20
27
|
%r{^(test|spec|features)/}
|
21
28
|
true
|
22
29
|
else
|
@@ -29,11 +36,11 @@ Gem::Specification.new do |spec|
|
|
29
36
|
spec.require_paths = ["lib"]
|
30
37
|
spec.extensions = ["ext/pycall/extconf.rb"]
|
31
38
|
|
32
|
-
spec.add_development_dependency "bundler"
|
33
|
-
spec.add_development_dependency "rake"
|
39
|
+
spec.add_development_dependency "bundler"
|
40
|
+
spec.add_development_dependency "rake"
|
34
41
|
spec.add_development_dependency "rake-compiler"
|
35
42
|
spec.add_development_dependency "rake-compiler-dock"
|
36
|
-
spec.add_development_dependency "rspec"
|
43
|
+
spec.add_development_dependency "rspec"
|
37
44
|
spec.add_development_dependency "launchy"
|
38
45
|
spec.add_development_dependency "pry"
|
39
46
|
spec.add_development_dependency "pry-byebug"
|
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pycall
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kenta Murata
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-05-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake-compiler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -70,16 +70,16 @@ dependencies:
|
|
70
70
|
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: launchy
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -130,6 +130,7 @@ extensions:
|
|
130
130
|
- ext/pycall/extconf.rb
|
131
131
|
extra_rdoc_files: []
|
132
132
|
files:
|
133
|
+
- ".github/workflows/ci.yml"
|
133
134
|
- ".gitignore"
|
134
135
|
- ".rspec"
|
135
136
|
- ".travis.yml"
|
@@ -167,11 +168,14 @@ files:
|
|
167
168
|
- ext/pycall/gc.c
|
168
169
|
- ext/pycall/libpython.c
|
169
170
|
- ext/pycall/pycall.c
|
171
|
+
- ext/pycall/pycall.h
|
170
172
|
- ext/pycall/pycall_internal.h
|
171
173
|
- ext/pycall/range.c
|
172
174
|
- ext/pycall/ruby_wrapper.c
|
175
|
+
- ext/pycall/thread.c
|
176
|
+
- images/pycallrb_logo.png
|
177
|
+
- images/pycallrb_logo_200.png
|
173
178
|
- lib/pycall.rb
|
174
|
-
- lib/pycall/conversion.rb
|
175
179
|
- lib/pycall/dict.rb
|
176
180
|
- lib/pycall/error.rb
|
177
181
|
- lib/pycall/gc_guard.rb
|
@@ -185,6 +189,7 @@ files:
|
|
185
189
|
- lib/pycall/list.rb
|
186
190
|
- lib/pycall/pretty_print.rb
|
187
191
|
- lib/pycall/pyerror.rb
|
192
|
+
- lib/pycall/pymodule_wrapper.rb
|
188
193
|
- lib/pycall/pyobject_wrapper.rb
|
189
194
|
- lib/pycall/python/PyCall/__init__.py
|
190
195
|
- lib/pycall/python/PyCall/six.py
|
@@ -192,7 +197,6 @@ files:
|
|
192
197
|
- lib/pycall/pytypeobject_wrapper.rb
|
193
198
|
- lib/pycall/set.rb
|
194
199
|
- lib/pycall/slice.rb
|
195
|
-
- lib/pycall/tuple.rb
|
196
200
|
- lib/pycall/version.rb
|
197
201
|
- lib/pycall/wrapper_object_cache.rb
|
198
202
|
- pycall.gemspec
|
@@ -217,8 +221,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
217
221
|
- !ruby/object:Gem::Version
|
218
222
|
version: '0'
|
219
223
|
requirements: []
|
220
|
-
|
221
|
-
rubygems_version: 2.6.13
|
224
|
+
rubygems_version: 3.1.2
|
222
225
|
signing_key:
|
223
226
|
specification_version: 4
|
224
227
|
summary: pycall
|