pybind 0.1.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 +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +25 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +132 -0
- data/Rakefile +5 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/examples/autocall_functions.rb +15 -0
- data/examples/hello_world.py +1 -0
- data/examples/hello_world.rb +14 -0
- data/examples/mnist.softmax.rb +53 -0
- data/examples/numpy.rb +9 -0
- data/lib/pybind.rb +14 -0
- data/lib/pybind/autocall.rb +14 -0
- data/lib/pybind/core_ext/basic.rb +66 -0
- data/lib/pybind/error.rb +38 -0
- data/lib/pybind/import.rb +51 -0
- data/lib/pybind/init.rb +23 -0
- data/lib/pybind/libpython.rb +371 -0
- data/lib/pybind/python/investigator.py +10 -0
- data/lib/pybind/struct.rb +36 -0
- data/lib/pybind/typecast.rb +28 -0
- data/lib/pybind/types.rb +21 -0
- data/lib/pybind/types/basic.rb +70 -0
- data/lib/pybind/types/dict.rb +94 -0
- data/lib/pybind/types/function.rb +26 -0
- data/lib/pybind/types/list.rb +39 -0
- data/lib/pybind/types/object.rb +9 -0
- data/lib/pybind/types/sequence.rb +26 -0
- data/lib/pybind/types/set.rb +19 -0
- data/lib/pybind/types/slice.rb +19 -0
- data/lib/pybind/types/tuple.rb +45 -0
- data/lib/pybind/utils.rb +81 -0
- data/lib/pybind/version.rb +3 -0
- data/lib/pybind/wrapper.rb +120 -0
- data/lib/pybind/wrapper/attr_accessor.rb +53 -0
- data/lib/pybind/wrapper/operator.rb +82 -0
- data/lib/pybind/wrapper/rich_comparer.rb +39 -0
- data/pybind.gemspec +40 -0
- metadata +157 -0
@@ -0,0 +1,10 @@
|
|
1
|
+
from distutils.sysconfig import get_config_var
|
2
|
+
import sys
|
3
|
+
|
4
|
+
print('EXECUTABLE: ' + str(sys.executable))
|
5
|
+
print('EXECPREFIX: ' + str(sys.exec_prefix))
|
6
|
+
print('PREFIX: ' + str(sys.prefix))
|
7
|
+
if sys.version_info >= (3, 3):
|
8
|
+
print('IMPLEMENTATIONMULTIARCH: ' + str(sys.implementation._multiarch))
|
9
|
+
for var in ('VERSION', 'INSTSONAME', 'LIBRARY', 'LDLIBRARY', 'LIBDIR', 'PYTHONFRAMEWORKPREFIX', 'MULTIARCH'):
|
10
|
+
print(var + ': ' + str(get_config_var(var)))
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module PyBind
|
4
|
+
class PyObjectStruct < FFI::Struct
|
5
|
+
layout ob_refcnt: :ssize_t,
|
6
|
+
ob_type: PyObjectStruct.by_ref
|
7
|
+
|
8
|
+
def self.null
|
9
|
+
new(FFI::Pointer::NULL)
|
10
|
+
end
|
11
|
+
|
12
|
+
def none?
|
13
|
+
PyBind.None.to_ptr == to_ptr
|
14
|
+
end
|
15
|
+
|
16
|
+
def kind_of?(klass)
|
17
|
+
case klass
|
18
|
+
when PyBind::PyObjectStruct
|
19
|
+
value = LibPython.PyObject_IsInstance(self, klass)
|
20
|
+
raise PyError.fetch if value == -1
|
21
|
+
value == 1
|
22
|
+
else
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_ruby_object
|
28
|
+
PyObject.new(self)
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_python_struct
|
32
|
+
self
|
33
|
+
end
|
34
|
+
alias_method :to_python, :to_python_struct
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module PyBind
|
2
|
+
module TypeCast
|
3
|
+
def self.from_python(pyobj)
|
4
|
+
pystruct = pyobj.to_python_struct
|
5
|
+
return nil if pystruct.null? || pystruct.none?
|
6
|
+
|
7
|
+
Types.pytypes.each do |pytype|
|
8
|
+
return pytype.from_python(pystruct) if pytype.python_instance?(pystruct)
|
9
|
+
end
|
10
|
+
PyObject.from_python(pystruct)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.to_python_arguments(indices)
|
14
|
+
if indices.length == 1
|
15
|
+
indices = indices[0]
|
16
|
+
else
|
17
|
+
indices = PyTuple.new(indices)
|
18
|
+
end
|
19
|
+
indices.to_python
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class PyObjectStruct
|
24
|
+
def to_ruby
|
25
|
+
TypeCast.from_python(self)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/pybind/types.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module PyBind
|
2
|
+
module Types
|
3
|
+
class << self
|
4
|
+
attr_reader :pytypes
|
5
|
+
end
|
6
|
+
|
7
|
+
@pytypes ||= []
|
8
|
+
def self.register_type(pytype)
|
9
|
+
@pytypes.unshift(pytype)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'pybind/core_ext/basic'
|
15
|
+
require 'pybind/types/basic'
|
16
|
+
require 'pybind/types/object'
|
17
|
+
require 'pybind/types/tuple'
|
18
|
+
require 'pybind/types/slice'
|
19
|
+
require 'pybind/types/list'
|
20
|
+
require 'pybind/types/dict'
|
21
|
+
require 'pybind/types/set'
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module PyBind
|
2
|
+
class PyType
|
3
|
+
include PyObjectWrapper
|
4
|
+
pybind_type LibPython.PyType_Type
|
5
|
+
|
6
|
+
def to_s
|
7
|
+
return super unless has_attribute?('__name__')
|
8
|
+
get_attribute('__name__')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class PyString
|
13
|
+
include PyObjectWrapper
|
14
|
+
|
15
|
+
pybind_type LibPython.PyString_Type do |pystruct|
|
16
|
+
FFI::MemoryPointer.new(:string) do |str_ptr|
|
17
|
+
FFI::MemoryPointer.new(:int) do |len_ptr|
|
18
|
+
res = LibPython.PyString_AsStringAndSize(pystruct, str_ptr, len_ptr)
|
19
|
+
return nil if res == -1 # FIXME: error
|
20
|
+
|
21
|
+
len = len_ptr.get(:int, 0)
|
22
|
+
return str_ptr.get_pointer(0).read_string(len)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class PyUnicode
|
29
|
+
include PyObjectWrapper
|
30
|
+
|
31
|
+
pybind_type LibPython.PyUnicode_Type do |pystruct|
|
32
|
+
pystruct = LibPython.PyUnicode_AsUTF8String(pystruct)
|
33
|
+
PyString.from_python(pystruct).force_encoding(Encoding::UTF_8)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class PyInt
|
38
|
+
include PyObjectWrapper
|
39
|
+
|
40
|
+
pybind_type LibPython.PyInt_Type do |pystruct|
|
41
|
+
LibPython.PyInt_AsSsize_t(pystruct)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class PyBool
|
46
|
+
include PyObjectWrapper
|
47
|
+
|
48
|
+
pybind_type LibPython.PyBool_Type do |pystruct|
|
49
|
+
LibPython.PyInt_AsSsize_t(pystruct) != 0
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class PyFloat
|
54
|
+
include PyObjectWrapper
|
55
|
+
|
56
|
+
pybind_type LibPython.PyFloat_Type do |pystruct|
|
57
|
+
LibPython.PyFloat_AsDouble(pystruct)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class PyComplex
|
62
|
+
include PyObjectWrapper
|
63
|
+
|
64
|
+
pybind_type LibPython.PyComplex_Type do |pystruct|
|
65
|
+
real = LibPython.PyComplex_RealAsDouble(pystruct)
|
66
|
+
imag = LibPython.PyComplex_ImagAsDouble(pystruct)
|
67
|
+
Complex(real, imag)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module PyBind
|
2
|
+
class PyDict
|
3
|
+
include Enumerable
|
4
|
+
include PyObjectWrapper
|
5
|
+
pybind_type LibPython.PyDict_Type
|
6
|
+
|
7
|
+
def self.new(init = nil)
|
8
|
+
case init
|
9
|
+
when PyObjectStruct
|
10
|
+
super
|
11
|
+
when nil
|
12
|
+
new(LibPython.PyDict_New())
|
13
|
+
when Hash
|
14
|
+
new.tap do |dict|
|
15
|
+
init.each do |key, value|
|
16
|
+
dict[key] = value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
else
|
20
|
+
raise TypeError, "the argument must be a PyObjectStruct or a Hash"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def [](key)
|
25
|
+
case key
|
26
|
+
when String, Symbol
|
27
|
+
LibPython.PyDict_GetItemString(@pystruct, key.to_s).to_ruby
|
28
|
+
else
|
29
|
+
key = key.to_python
|
30
|
+
LibPython.PyDict_GetItem(@pystruct, key).to_ruby
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def []=(key, value)
|
35
|
+
value = value.to_python
|
36
|
+
case key
|
37
|
+
when String, Symbol
|
38
|
+
LibPython.PyDict_SetItemString(@pystruct, key.to_s, value)
|
39
|
+
else
|
40
|
+
key = key.to_python
|
41
|
+
LibPython.PyDict_SetItem(@pystruct, key, value)
|
42
|
+
end
|
43
|
+
value
|
44
|
+
end
|
45
|
+
|
46
|
+
def delete(key)
|
47
|
+
case key
|
48
|
+
when String, Symbol
|
49
|
+
value = LibPython.PyDict_GetItemString(@pystruct, key).to_ruby
|
50
|
+
LibPython.PyDict_DelItemString(@pystruct, key.to_s)
|
51
|
+
else
|
52
|
+
key = key.to_python
|
53
|
+
value = LibPython.PyDict_GetItem(@pystruct, key).to_ruby
|
54
|
+
LibPython.PyDict_DelItem(@pystruct, key)
|
55
|
+
end
|
56
|
+
value
|
57
|
+
end
|
58
|
+
|
59
|
+
def size
|
60
|
+
LibPython.PyDict_Size(@pystruct)
|
61
|
+
end
|
62
|
+
|
63
|
+
def keys
|
64
|
+
LibPython.PyDict_Keys(@pystruct).to_ruby
|
65
|
+
end
|
66
|
+
|
67
|
+
def values
|
68
|
+
LibPython.PyDict_Values(@pystruct).to_ruby
|
69
|
+
end
|
70
|
+
|
71
|
+
def has_key?(key)
|
72
|
+
key = key.to_python
|
73
|
+
value = LibPython.PyDict_Contains(@pystruct, key)
|
74
|
+
raise PyError.fetch if value == -1
|
75
|
+
value == 1
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_a
|
79
|
+
LibPython.PyDict_Items(@pystruct).to_ruby
|
80
|
+
end
|
81
|
+
|
82
|
+
def to_hash
|
83
|
+
Hash[to_a]
|
84
|
+
end
|
85
|
+
|
86
|
+
def each
|
87
|
+
return enum_for unless block_given?
|
88
|
+
keys.each do |key|
|
89
|
+
yield key, self[key]
|
90
|
+
end
|
91
|
+
self
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module PyBind
|
2
|
+
module PyCallable
|
3
|
+
end
|
4
|
+
|
5
|
+
class PyFunction
|
6
|
+
include PyCallable
|
7
|
+
include PyObjectWrapper
|
8
|
+
pybind_type PyBind.types.FunctionType
|
9
|
+
end
|
10
|
+
|
11
|
+
class PyMethod
|
12
|
+
include PyCallable
|
13
|
+
include PyObjectWrapper
|
14
|
+
pybind_type PyBind.types.MethodType
|
15
|
+
end
|
16
|
+
|
17
|
+
class PyBuiltinFunction
|
18
|
+
include PyCallable
|
19
|
+
include PyObjectWrapper
|
20
|
+
pybind_type PyBind.types.BuiltinFunctionType
|
21
|
+
end
|
22
|
+
|
23
|
+
class PyType
|
24
|
+
include PyCallable
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'pybind/types/sequence'
|
2
|
+
|
3
|
+
module PyBind
|
4
|
+
class PyList
|
5
|
+
include PyObjectWrapper
|
6
|
+
pybind_type LibPython.PyList_Type
|
7
|
+
|
8
|
+
include PySequence
|
9
|
+
|
10
|
+
def self.new(init = nil)
|
11
|
+
case init
|
12
|
+
when PyObjectStruct
|
13
|
+
super
|
14
|
+
when nil
|
15
|
+
new(0)
|
16
|
+
when Integer
|
17
|
+
new(LibPython.PyList_New(init))
|
18
|
+
when Array
|
19
|
+
new.tap do |list|
|
20
|
+
init.each do |item|
|
21
|
+
list << item
|
22
|
+
end
|
23
|
+
end
|
24
|
+
else
|
25
|
+
raise TypeError, "the argument must be an Integer, a PyObjectStruct or a Array"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def <<(value)
|
30
|
+
value = value.to_python
|
31
|
+
LibPython.PyList_Append(@pystruct, value)
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def size
|
36
|
+
LibPython.PyList_Size(@pystruct)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module PyBind
|
2
|
+
module PySequence
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def include?(value)
|
6
|
+
value = value.to_python
|
7
|
+
value = LibPython.PySequence_Contains(@pystruct, value)
|
8
|
+
raise PyError.fetch if value == -1
|
9
|
+
value == 1
|
10
|
+
end
|
11
|
+
|
12
|
+
def each
|
13
|
+
return enum_for unless block_given?
|
14
|
+
size.times do |i|
|
15
|
+
yield self[i]
|
16
|
+
end
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_a
|
21
|
+
each.to_a
|
22
|
+
end
|
23
|
+
|
24
|
+
alias_method :to_ary, :to_a
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module PyBind
|
2
|
+
class PySet
|
3
|
+
include PyObjectWrapper
|
4
|
+
pybind_type LibPython.PySet_Type
|
5
|
+
|
6
|
+
def initialize(init)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def size
|
11
|
+
LibPython.PySet_Size(@pystruct)
|
12
|
+
end
|
13
|
+
|
14
|
+
def include?(obj)
|
15
|
+
obj = obj.to_python
|
16
|
+
LibPython.PySet_Contains(@pystruct, obj) == 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module PyBind
|
2
|
+
class PySlice
|
3
|
+
include PyObjectWrapper
|
4
|
+
pybind_type LibPython.PySlice_Type
|
5
|
+
|
6
|
+
def self.new(start, stop = nil, step = nil)
|
7
|
+
if stop.nil? && step.nil?
|
8
|
+
start, stop = nil, start
|
9
|
+
return super(stop) if stop.kind_of?(PyObjectStruct)
|
10
|
+
end
|
11
|
+
start = start ? start.to_python : PyObjectStruct.null
|
12
|
+
stop = stop ? stop.to_python : PyObjectStruct.null
|
13
|
+
step = step ? step.to_python : PyObjectStruct.null
|
14
|
+
pyobj = LibPython.PySlice_New(start, stop, step)
|
15
|
+
raise PyError.fetch if pyobj.null?
|
16
|
+
pyobj.to_ruby
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'pybind/types/sequence'
|
2
|
+
|
3
|
+
module PyBind
|
4
|
+
class PyTuple
|
5
|
+
include PyObjectWrapper
|
6
|
+
pybind_type LibPython.PyTuple_Type
|
7
|
+
|
8
|
+
include PySequence
|
9
|
+
|
10
|
+
def self.new(init)
|
11
|
+
case init
|
12
|
+
when PyObjectStruct
|
13
|
+
super
|
14
|
+
when Integer
|
15
|
+
super(LibPython.PyTuple_New(init))
|
16
|
+
when Array
|
17
|
+
tuple = new(init.size)
|
18
|
+
init.each_with_index do |obj, index|
|
19
|
+
tuple[index] = obj
|
20
|
+
end
|
21
|
+
tuple
|
22
|
+
else
|
23
|
+
raise TypeError, "the argument must be an Integer, a PyObjectStruct or a Array"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Make tuple from array
|
28
|
+
def self.[](*ary)
|
29
|
+
new(ary)
|
30
|
+
end
|
31
|
+
|
32
|
+
def size
|
33
|
+
LibPython.PyTuple_Size(@pystruct)
|
34
|
+
end
|
35
|
+
|
36
|
+
def [](index)
|
37
|
+
LibPython.PyTuple_GetItem(@pystruct, index).to_ruby
|
38
|
+
end
|
39
|
+
|
40
|
+
def []=(index, value)
|
41
|
+
value = value.to_python
|
42
|
+
LibPython.PyTuple_SetItem(@pystruct, index, value)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|