pycall 1.2.0.beta1 → 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 +4 -4
- data/.github/workflows/ci.yml +67 -0
- data/.travis.yml +45 -19
- data/CHANGES.md +31 -1
- data/README.md +50 -1
- data/appveyor.yml +0 -12
- 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 +7 -1
- data/ext/pycall/pycall.c +60 -6
- data/ext/pycall/pycall_internal.h +26 -0
- data/ext/pycall/thread.c +36 -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 +9 -10
- 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 +10 -0
- data/lib/pycall/version.rb +7 -1
- data/pycall.gemspec +10 -4
- metadata +20 -18
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ba0b7938e482d87e6a6eb540b92b2e581974fc6e894e674c7da00b4b68807b15
|
|
4
|
+
data.tar.gz: ad5ce0352f59744abf9193e69cf33719f9314aad45e9c24fd6584fe73873330e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cc2eb8963c91d69086eccab17cb06ebea072908f77f3e4f85a23f328f858f7cda29ebec70c519fa70f3fc88eaf5e37b61b88136515f2326e0c239467a522067b
|
|
7
|
+
data.tar.gz: cfb14589abee3741fcec45f31d8d94dc076341ae425ee0302e50628e6ffafdfff665a6e90c67a80ce10df6a8866282bc221ecddf198d0049ee85d1055bb50255
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
- push
|
|
5
|
+
|
|
6
|
+
jobs:
|
|
7
|
+
test:
|
|
8
|
+
name: Test
|
|
9
|
+
runs-on: ${{ matrix.os }}
|
|
10
|
+
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
os:
|
|
15
|
+
- ubuntu-18.04
|
|
16
|
+
- macos-latest
|
|
17
|
+
ruby_version:
|
|
18
|
+
- 2.7.x
|
|
19
|
+
- 2.6.x
|
|
20
|
+
- 2.5.x
|
|
21
|
+
- 2.4.x
|
|
22
|
+
python_version:
|
|
23
|
+
- 3.8.x
|
|
24
|
+
- 3.7.x
|
|
25
|
+
- 3.6.x
|
|
26
|
+
- 2.7.x
|
|
27
|
+
python_architecture:
|
|
28
|
+
- x64
|
|
29
|
+
|
|
30
|
+
steps:
|
|
31
|
+
- name: Setup Ruby
|
|
32
|
+
if: matrix.ruby_version != 'master-nightly'
|
|
33
|
+
uses: actions/setup-ruby@v1
|
|
34
|
+
with:
|
|
35
|
+
ruby-version: ${{ matrix.ruby_version }}
|
|
36
|
+
|
|
37
|
+
- name: Setup Python
|
|
38
|
+
uses: actions/setup-python@v1
|
|
39
|
+
with:
|
|
40
|
+
python-version: ${{ matrix.python_version }}
|
|
41
|
+
architecture: ${{ matrix.python_architecture }}
|
|
42
|
+
|
|
43
|
+
- name: Checkout
|
|
44
|
+
uses: actions/checkout@v1
|
|
45
|
+
with:
|
|
46
|
+
fetch-depth: 1
|
|
47
|
+
|
|
48
|
+
- name: Prepare environment
|
|
49
|
+
run: |
|
|
50
|
+
gem install bundler
|
|
51
|
+
|
|
52
|
+
- name: Install requirements
|
|
53
|
+
run: |
|
|
54
|
+
pip install --user numpy
|
|
55
|
+
bundle install
|
|
56
|
+
|
|
57
|
+
- name: Compile pycall.so
|
|
58
|
+
run: |
|
|
59
|
+
bundle exec rake compile
|
|
60
|
+
|
|
61
|
+
- name: Python investigator
|
|
62
|
+
run: |
|
|
63
|
+
python lib/pycall/python/investigator.py
|
|
64
|
+
|
|
65
|
+
- name: Test
|
|
66
|
+
run: |
|
|
67
|
+
PYTHON=python bundle exec rake
|
data/.travis.yml
CHANGED
|
@@ -2,48 +2,74 @@ language: ruby
|
|
|
2
2
|
|
|
3
3
|
os: linux
|
|
4
4
|
|
|
5
|
-
dist:
|
|
5
|
+
dist: bionic
|
|
6
6
|
sudo: required
|
|
7
7
|
|
|
8
8
|
rvm:
|
|
9
9
|
- ruby-head
|
|
10
|
-
- 2.
|
|
11
|
-
- 2.
|
|
12
|
-
- 2.
|
|
10
|
+
- 2.7
|
|
11
|
+
- 2.6
|
|
12
|
+
- 2.5
|
|
13
|
+
- 2.4
|
|
13
14
|
|
|
14
15
|
env:
|
|
15
16
|
global:
|
|
16
17
|
- PYCALL_DEBUG_FIND_LIBPYTHON=1
|
|
17
18
|
matrix:
|
|
18
|
-
- PYENV_VERSION=
|
|
19
|
-
- PYENV_VERSION=3.
|
|
20
|
-
- PYENV_VERSION=
|
|
21
|
-
- PYENV_VERSION=
|
|
22
|
-
- PYENV_VERSION=
|
|
19
|
+
- PYENV_VERSION=3.8.0
|
|
20
|
+
- PYENV_VERSION=3.7.5
|
|
21
|
+
- PYENV_VERSION=2.7.17
|
|
22
|
+
- PYENV_VERSION=system LIBPYTHON=/usr/lib/x86_64-linux-gnu/libpython3.6m.so
|
|
23
|
+
- PYENV_VERSION=system LIBPYTHON=/usr/lib/x86_64-linux-gnu/libpython2.7.so
|
|
24
|
+
- PYENV_VERSION=miniconda2-4.3.30
|
|
25
|
+
- PYENV_VERSION=miniconda3-4.3.30
|
|
23
26
|
|
|
24
27
|
matrix:
|
|
25
28
|
include:
|
|
26
29
|
- os: osx
|
|
27
|
-
osx_image:
|
|
30
|
+
osx_image: xcode11.2
|
|
28
31
|
compiler: clang
|
|
29
|
-
rvm: 2.
|
|
30
|
-
env: PYENV_VERSION=3.
|
|
32
|
+
rvm: 2.7
|
|
33
|
+
env: PYENV_VERSION=3.8.0
|
|
31
34
|
- os: osx
|
|
32
|
-
osx_image:
|
|
35
|
+
osx_image: xcode11.2
|
|
33
36
|
compiler: clang
|
|
34
|
-
rvm: 2.
|
|
35
|
-
env: PYENV_VERSION=
|
|
37
|
+
rvm: 2.6
|
|
38
|
+
env: PYENV_VERSION=3.8.0
|
|
36
39
|
- os: osx
|
|
37
|
-
osx_image:
|
|
40
|
+
osx_image: xcode11.2
|
|
38
41
|
compiler: clang
|
|
39
|
-
rvm: 2.
|
|
42
|
+
rvm: 2.5
|
|
43
|
+
env: PYENV_VERSION=3.8.0
|
|
44
|
+
- os: osx
|
|
45
|
+
osx_image: xcode11.2
|
|
46
|
+
compiler: clang
|
|
47
|
+
rvm: 2.4
|
|
48
|
+
env: PYENV_VERSION=3.8.0
|
|
49
|
+
- os: osx
|
|
50
|
+
osx_image: xcode11.2
|
|
51
|
+
compiler: clang
|
|
52
|
+
rvm: 2.7
|
|
53
|
+
env: PYENV_VERSION=miniconda3-4.3.11
|
|
54
|
+
- os: osx
|
|
55
|
+
osx_image: xcode11.2
|
|
56
|
+
compiler: clang
|
|
57
|
+
rvm: 2.6
|
|
58
|
+
env: PYENV_VERSION=miniconda3-4.3.11
|
|
59
|
+
- os: osx
|
|
60
|
+
osx_image: xcode11.2
|
|
61
|
+
compiler: clang
|
|
62
|
+
rvm: 2.5
|
|
63
|
+
env: PYENV_VERSION=miniconda3-4.3.11
|
|
64
|
+
- os: osx
|
|
65
|
+
osx_image: xcode11.2
|
|
66
|
+
compiler: clang
|
|
67
|
+
rvm: 2.4
|
|
40
68
|
env: PYENV_VERSION=miniconda3-4.3.11
|
|
41
69
|
allow_failures:
|
|
42
70
|
- os: osx
|
|
43
71
|
|
|
44
72
|
before_install:
|
|
45
|
-
- gem update --system
|
|
46
|
-
- gem update bundler
|
|
47
73
|
- export PATH="$(pyenv root)/bin:$PATH"
|
|
48
74
|
- eval "$(pyenv init -)"
|
|
49
75
|
|
data/CHANGES.md
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
# The change history of PyCall
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 1.3.1
|
|
4
|
+
|
|
5
|
+
* Stop using `&proc` idiom to prevent warnings
|
|
6
|
+
|
|
7
|
+
*Kenta Murata*
|
|
8
|
+
|
|
9
|
+
## 1.3.0
|
|
10
|
+
|
|
11
|
+
* Add `PyCall.without_gvl` for explicitly releasing the RubyVM GVL
|
|
12
|
+
|
|
13
|
+
* Fix for missing if in PyObjectWrapper
|
|
14
|
+
|
|
15
|
+
*Kouhei Sutou*
|
|
16
|
+
|
|
17
|
+
* Fix for Anaconda environment
|
|
18
|
+
|
|
19
|
+
*Ryo MATSUMIYA*
|
|
20
|
+
|
|
21
|
+
* Fix against `unknown symbol "PyInt_AsSsize_t"` (Fiddle::DLError)
|
|
22
|
+
|
|
23
|
+
*Kouhei Sutou*
|
|
24
|
+
|
|
25
|
+
* Fix for `TypeError: Compared with non class/module`
|
|
26
|
+
|
|
27
|
+
*Archonic*
|
|
28
|
+
|
|
29
|
+
## 1.2.1
|
|
30
|
+
|
|
31
|
+
* Prevent circular require in pycall/iruby.rb
|
|
32
|
+
|
|
33
|
+
## 1.2.0
|
|
4
34
|
|
|
5
35
|
* Add `PyCall::Tuple#to_ary`
|
|
6
36
|
|
data/README.md
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
# PyCall: Calling Python functions from the Ruby language
|
|
7
7
|
|
|
8
|
+
[](https://github.com/mrkn/pycall.rb/actions?query=workflow%3ACI)
|
|
8
9
|
[](https://travis-ci.org/mrkn/pycall.rb)
|
|
9
|
-
[](https://ci.appveyor.com/project/mrkn/pycall-rb/branch/master)
|
|
10
11
|
|
|
11
12
|
This library provides the features to directly call and partially interoperate
|
|
12
13
|
with Python from the Ruby language. You can import arbitrary Python modules
|
|
@@ -23,6 +24,15 @@ pycall.rb supports Python version 2.7 or higher.
|
|
|
23
24
|
|
|
24
25
|
Note that in Python 2.7 old-style class, that is defined without a super class, is not fully supported in pycall.rb.
|
|
25
26
|
|
|
27
|
+
## Note for pyenv users
|
|
28
|
+
|
|
29
|
+
pycall.rb requires Python's shared library (e.g. `libpython3.7m.so`).
|
|
30
|
+
pyenv does not build the shared library in default, so you need to specify `--enable-shared` option at the installation like below:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
$ env PYTHON_CONFIGURE_OPTS='--enable-shared' pyenv install 3.7.2
|
|
34
|
+
```
|
|
35
|
+
|
|
26
36
|
## Installation
|
|
27
37
|
|
|
28
38
|
Add this line to your application's Gemfile:
|
|
@@ -52,6 +62,45 @@ the `Math.sin` in Ruby:
|
|
|
52
62
|
Type conversions from Ruby to Python are automatically performed for numeric,
|
|
53
63
|
boolean, string, arrays, and hashes.
|
|
54
64
|
|
|
65
|
+
### Releasing the RubyVM GVL during Python function calls
|
|
66
|
+
|
|
67
|
+
You may want to release the RubyVM GVL when you call a Python function that takes very long runtime.
|
|
68
|
+
PyCall provides `PyCall.without_gvl` method for such purpose. When PyCall performs python function call,
|
|
69
|
+
PyCall checks the current context, and then it releases the RubyVM GVL when the current context is in a `PyCall.without_gvl`'s block.
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
PyCall.without_gvl do
|
|
73
|
+
# In this block, all Python function calls are performed without
|
|
74
|
+
# the GVL acquisition.
|
|
75
|
+
pyobj.long_running_function()
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Outside of PyCall.without_gvl block,
|
|
79
|
+
# all Python function calls are performed with the GVL acquisition.
|
|
80
|
+
pyobj.long_running_function()
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Debugging python finder
|
|
84
|
+
|
|
85
|
+
When you encounter `PyCall::PythonNotFound` error, you can investigate PyCall's python finder by setting `PYCALL_DEBUG_FIND_LIBPYTHON` environment variable to `1`. You can see the log like below:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
$ PYCALL_DEBUG_FIND_LIBPYTHON=1 ruby -rpycall -ePyCall.builtins
|
|
89
|
+
DEBUG(find_libpython) find_libpython(nil)
|
|
90
|
+
DEBUG(find_libpython) investigate_python_config("python3")
|
|
91
|
+
DEBUG(find_libpython) libs: ["Python.framework/Versions/3.7/Python", "Python", "libpython3.7m", "libpython3.7", "libpython"]
|
|
92
|
+
DEBUG(find_libpython) libpaths: ["/opt/brew/opt/python/Frameworks/Python.framework/Versions/3.7/lib", "/opt/brew/opt/python/lib", "/opt/brew/opt/python/Frameworks", "/opt/brew/Cellar/python/3.7.2_1/Frameworks/Python.framework/Versions/3.7", "/opt/brew/Cellar/python/3.7.2_1/Frameworks/Python.framework/Versions/3.7/lib"]
|
|
93
|
+
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/Frameworks/Python.framework/Versions/3.7/lib/Python.framework/Versions/3.7/Python
|
|
94
|
+
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/Frameworks/Python.framework/Versions/3.7/lib/Python.framework/Versions/3.7/Python.dylib
|
|
95
|
+
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/Frameworks/Python.framework/Versions/3.7/lib/darwin/Python.framework/Versions/3.7/Python
|
|
96
|
+
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/Frameworks/Python.framework/Versions/3.7/lib/darwin/Python.framework/Versions/3.7/Python.dylib
|
|
97
|
+
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/lib/Python.framework/Versions/3.7/Python
|
|
98
|
+
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/lib/Python.framework/Versions/3.7/Python.dylib
|
|
99
|
+
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/lib/darwin/Python.framework/Versions/3.7/Python
|
|
100
|
+
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/lib/darwin/Python.framework/Versions/3.7/Python.dylib
|
|
101
|
+
DEBUG(find_libpython) dlopen("/opt/brew/opt/python/Frameworks/Python.framework/Versions/3.7/Python") = #<Fiddle::Handle:0x00007fc012048650>
|
|
102
|
+
```
|
|
103
|
+
|
|
55
104
|
## PyCall object system
|
|
56
105
|
|
|
57
106
|
PyCall wraps pointers of Python objects in `PyCall::PyPtr` objects.
|
data/appveyor.yml
CHANGED
|
@@ -6,10 +6,6 @@ environment:
|
|
|
6
6
|
PYTHONDIR: "C:\\Python27"
|
|
7
7
|
PYTHON: "C:\\Python27\\python.exe"
|
|
8
8
|
|
|
9
|
-
- ruby_version: "24"
|
|
10
|
-
PYTHONDIR: "C:\\Python34"
|
|
11
|
-
PYTHON: "C:\\Python34\\python.exe"
|
|
12
|
-
|
|
13
9
|
- ruby_version: "24"
|
|
14
10
|
PYTHONDIR: "C:\\Python35"
|
|
15
11
|
PYTHON: "C:\\Python35\\python.exe"
|
|
@@ -23,10 +19,6 @@ environment:
|
|
|
23
19
|
PYTHONDIR: "C:\\Python27-x64"
|
|
24
20
|
PYTHON: "C:\\Python27-x64\\python.exe"
|
|
25
21
|
|
|
26
|
-
- ruby_version: "24-x64"
|
|
27
|
-
PYTHONDIR: "C:\\Python34-x64"
|
|
28
|
-
PYTHON: "C:\\Python34-x64\\python.exe"
|
|
29
|
-
|
|
30
22
|
- ruby_version: "24-x64"
|
|
31
23
|
PYTHONDIR: "C:\\Python35-x64"
|
|
32
24
|
PYTHON: "C:\\Python35-x64\\python.exe"
|
|
@@ -57,10 +49,6 @@ environment:
|
|
|
57
49
|
PYTHONDIR: "C:\\Python27-x64"
|
|
58
50
|
PYTHON: "C:\\Python27-x64\\python.exe"
|
|
59
51
|
|
|
60
|
-
- ruby_version: "23-x64"
|
|
61
|
-
PYTHONDIR: "C:\\Python34-x64"
|
|
62
|
-
PYTHON: "C:\\Python34-x64\\python.exe"
|
|
63
|
-
|
|
64
52
|
- ruby_version: "23-x64"
|
|
65
53
|
PYTHONDIR: "C:\\Python35-x64"
|
|
66
54
|
PYTHON: "C:\\Python35-x64\\python.exe"
|
data/ci/travis_install.sh
CHANGED
|
@@ -10,19 +10,35 @@ if test -z "$PYENV_VERSION"; then
|
|
|
10
10
|
exit 1
|
|
11
11
|
fi
|
|
12
12
|
|
|
13
|
+
pyenv_root=$(pyenv root)
|
|
14
|
+
|
|
13
15
|
if test -n "$LIBPYTHON"; then
|
|
14
|
-
|
|
16
|
+
if test ! -f $LIBPYTHON; then
|
|
17
|
+
if test -f ${pyenv_root}/$LIBPYTHON; then
|
|
18
|
+
export LIBPYTHON=${pyenv_root}/$LIBPYTHON
|
|
19
|
+
else
|
|
20
|
+
echo "Invalid value in LIBPYTHON: ${LIBPYTHON}" >&2
|
|
21
|
+
exit 1
|
|
22
|
+
fi
|
|
23
|
+
fi
|
|
15
24
|
fi
|
|
16
25
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
26
|
+
(
|
|
27
|
+
cd $(pyenv root)
|
|
28
|
+
if [ -d .git ]; then
|
|
29
|
+
git fetch origin
|
|
30
|
+
git checkout master
|
|
31
|
+
git reset --hard origin/master
|
|
21
32
|
fi
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
case $PYENV_VERSION in
|
|
36
|
+
system)
|
|
37
|
+
;;
|
|
38
|
+
*)
|
|
39
|
+
PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install -f $PYENV_VERSION
|
|
40
|
+
;;
|
|
41
|
+
esac
|
|
26
42
|
|
|
27
43
|
case "$PYENV_VERSION" in
|
|
28
44
|
*conda*)
|
|
@@ -40,6 +56,11 @@ case "$PYENV_VERSION" in
|
|
|
40
56
|
travis_retry conda create -q -n test-environment python=$python_version numpy
|
|
41
57
|
source $(pyenv prefix)/bin/activate test-environment
|
|
42
58
|
;;
|
|
59
|
+
system)
|
|
60
|
+
travis_retry pip install --user numpy
|
|
61
|
+
sudo sh -c "apt-get update && apt-get install --no-install-recommends -y python3-pip"
|
|
62
|
+
travis_retry python3.6 -m pip install --user numpy
|
|
63
|
+
;;
|
|
43
64
|
*)
|
|
44
65
|
travis_retry pip install --user numpy
|
|
45
66
|
;;
|
|
@@ -2,7 +2,7 @@ require 'pycall/import'
|
|
|
2
2
|
include PyCall::Import
|
|
3
3
|
|
|
4
4
|
pyimport 'numpy', as: :np
|
|
5
|
-
pyfrom 'sklearn.
|
|
5
|
+
pyfrom 'sklearn.model_selection', import: :train_test_split
|
|
6
6
|
pyfrom 'sklearn.preprocessing', import: :StandardScaler
|
|
7
7
|
pyfrom 'sklearn.datasets', import: %i(make_moons make_circles make_classification)
|
|
8
8
|
pyfrom 'sklearn.neighbors', import: :KNeighborsClassifier
|
data/examples/hist.rb
CHANGED
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"include PyCall::Import\n",
|
|
39
39
|
"\n",
|
|
40
40
|
"pyimport 'numpy', as: :np\n",
|
|
41
|
-
"pyfrom 'sklearn.
|
|
41
|
+
"pyfrom 'sklearn.model_selection', import: :train_test_split\n",
|
|
42
42
|
"pyfrom 'sklearn.preprocessing', import: :StandardScaler\n",
|
|
43
43
|
"pyfrom 'sklearn.datasets', import: %i(make_moons make_circles make_classification)\n",
|
|
44
44
|
"pyfrom 'sklearn.neighbors', import: :KNeighborsClassifier\n",
|
data/ext/pycall/libpython.c
CHANGED
|
@@ -30,7 +30,13 @@ lookup_libpython_api(VALUE libpython_handle, char const *name)
|
|
|
30
30
|
arg.libpython_handle = libpython_handle;
|
|
31
31
|
arg.name = name;
|
|
32
32
|
addr = rb_protect((VALUE (*)(VALUE))lookup_libpython_api_0, (VALUE)&arg, &state);
|
|
33
|
-
|
|
33
|
+
if (state) {
|
|
34
|
+
rb_set_errinfo(Qnil);
|
|
35
|
+
return NULL;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
return NIL_P(addr) ? NULL : NUM2PTR(addr);
|
|
39
|
+
}
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
#define LOOKUP_API_ENTRY(api_name) lookup_libpython_api(libpython_handle, #api_name)
|
data/ext/pycall/pycall.c
CHANGED
|
@@ -70,6 +70,52 @@ pycall_after_fork(VALUE mod)
|
|
|
70
70
|
return Qnil;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
static volatile pycall_tls_key without_gvl_key;
|
|
74
|
+
|
|
75
|
+
int
|
|
76
|
+
pycall_without_gvl_p(void)
|
|
77
|
+
{
|
|
78
|
+
/*
|
|
79
|
+
* In pthread, the default value is NULL (== 0).
|
|
80
|
+
*
|
|
81
|
+
* In Win32 thread, the default value is 0 (initialized by TlsAlloc).
|
|
82
|
+
*/
|
|
83
|
+
return (int)pycall_tls_get(without_gvl_key);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
static inline int
|
|
87
|
+
pycall_set_without_gvl(void)
|
|
88
|
+
{
|
|
89
|
+
return pycall_tls_set(without_gvl_key, (void *)1);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
static inline int
|
|
93
|
+
pycall_set_with_gvl(void)
|
|
94
|
+
{
|
|
95
|
+
return pycall_tls_set(without_gvl_key, (void *)0);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
VALUE
|
|
99
|
+
pycall_without_gvl(VALUE (* func)(VALUE), VALUE arg)
|
|
100
|
+
{
|
|
101
|
+
int state;
|
|
102
|
+
VALUE result;
|
|
103
|
+
|
|
104
|
+
pycall_set_without_gvl();
|
|
105
|
+
|
|
106
|
+
result = rb_protect(func, arg, &state);
|
|
107
|
+
|
|
108
|
+
pycall_set_with_gvl();
|
|
109
|
+
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
static VALUE
|
|
114
|
+
pycall_m_without_gvl(VALUE mod)
|
|
115
|
+
{
|
|
116
|
+
return pycall_without_gvl(rb_yield, Qnil);
|
|
117
|
+
}
|
|
118
|
+
|
|
73
119
|
/* ==== PyCall::PyPtr ==== */
|
|
74
120
|
|
|
75
121
|
const rb_data_type_t pycall_pyptr_data_type = {
|
|
@@ -890,7 +936,7 @@ struct call_pyobject_call_params {
|
|
|
890
936
|
PyObject *kwargs;
|
|
891
937
|
};
|
|
892
938
|
|
|
893
|
-
PyObject *
|
|
939
|
+
static inline PyObject *
|
|
894
940
|
call_pyobject_call(struct call_pyobject_call_params *params)
|
|
895
941
|
{
|
|
896
942
|
PyObject *res;
|
|
@@ -899,7 +945,7 @@ call_pyobject_call(struct call_pyobject_call_params *params)
|
|
|
899
945
|
}
|
|
900
946
|
|
|
901
947
|
PyObject *
|
|
902
|
-
|
|
948
|
+
pyobject_call(PyObject *pycallable, PyObject *args, PyObject *kwargs)
|
|
903
949
|
{
|
|
904
950
|
PyObject *res;
|
|
905
951
|
struct call_pyobject_call_params params;
|
|
@@ -907,9 +953,14 @@ pyobject_call_without_gvl(PyObject *pycallable, PyObject *args, PyObject *kwargs
|
|
|
907
953
|
params.args = args;
|
|
908
954
|
params.kwargs = kwargs;
|
|
909
955
|
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
956
|
+
if (pycall_without_gvl_p()) {
|
|
957
|
+
res = (PyObject *)rb_thread_call_without_gvl(
|
|
958
|
+
(void * (*)(void *))call_pyobject_call, (void *)¶ms,
|
|
959
|
+
(rb_unblock_function_t *)pycall_interrupt_python_thread, NULL);
|
|
960
|
+
}
|
|
961
|
+
else {
|
|
962
|
+
res = call_pyobject_call(¶ms);
|
|
963
|
+
}
|
|
913
964
|
|
|
914
965
|
return res;
|
|
915
966
|
}
|
|
@@ -961,7 +1012,7 @@ pycall_call_python_callable(PyObject *pycallable, int argc, VALUE *argv)
|
|
|
961
1012
|
}
|
|
962
1013
|
}
|
|
963
1014
|
|
|
964
|
-
res =
|
|
1015
|
+
res = pyobject_call(pycallable, args, kwargs); /* New reference */
|
|
965
1016
|
if (!res) {
|
|
966
1017
|
pycall_pyerror_fetch_and_raise("PyObject_Call in pycall_call_python_callable");
|
|
967
1018
|
}
|
|
@@ -2185,6 +2236,9 @@ Init_pycall(void)
|
|
|
2185
2236
|
|
|
2186
2237
|
rb_define_module_function(mPyCall, "after_fork", pycall_after_fork, 0);
|
|
2187
2238
|
|
|
2239
|
+
pycall_tls_create(&without_gvl_key);
|
|
2240
|
+
rb_define_module_function(mPyCall, "without_gvl", pycall_m_without_gvl, 0);
|
|
2241
|
+
|
|
2188
2242
|
/* PyCall::PyPtr */
|
|
2189
2243
|
|
|
2190
2244
|
cPyPtr = rb_define_class_under(mPyCall, "PyPtr", rb_cBasicObject);
|
|
@@ -11,10 +11,19 @@ extern "C" {
|
|
|
11
11
|
#include <ruby.h>
|
|
12
12
|
#include <ruby/encoding.h>
|
|
13
13
|
#include <ruby/thread.h>
|
|
14
|
+
|
|
14
15
|
#include <assert.h>
|
|
15
16
|
#include <inttypes.h>
|
|
16
17
|
#include <limits.h>
|
|
17
18
|
|
|
19
|
+
#if defined(_WIN32)
|
|
20
|
+
# define PYCALL_THREAD_WIN32
|
|
21
|
+
# include <ruby/win32.h>
|
|
22
|
+
#elif defined(HAVE_PTHREAD_H)
|
|
23
|
+
# define PYCALL_THREAD_PTHREAD
|
|
24
|
+
# include <pthread.h>
|
|
25
|
+
#endif
|
|
26
|
+
|
|
18
27
|
#if SIZEOF_LONG == SIZEOF_VOIDP
|
|
19
28
|
# define PTR2NUM(x) (LONG2NUM((long)(x)))
|
|
20
29
|
# define NUM2PTR(x) ((void*)(NUM2ULONG(x)))
|
|
@@ -492,6 +501,23 @@ extern PyTypeObject PyRuby_Type;
|
|
|
492
501
|
|
|
493
502
|
PyObject * PyRuby_New(VALUE ruby_object);
|
|
494
503
|
|
|
504
|
+
/* ==== thread support ==== */
|
|
505
|
+
|
|
506
|
+
#if defined(PYCALL_THREAD_WIN32)
|
|
507
|
+
typedef DWORD pycall_tls_key;
|
|
508
|
+
#elif defined(PYCALL_THREAD_PTHREAD)
|
|
509
|
+
typedef pthread_key_t pycall_tls_key;
|
|
510
|
+
#else
|
|
511
|
+
# error "unsupported thread type"
|
|
512
|
+
#endif
|
|
513
|
+
|
|
514
|
+
int pycall_tls_create(pycall_tls_key* tls_key);
|
|
515
|
+
void *pycall_tls_get(pycall_tls_key tls_key);
|
|
516
|
+
int pycall_tls_set(pycall_tls_key tls_key, void *ptr);
|
|
517
|
+
|
|
518
|
+
int pycall_without_gvl_p(void);
|
|
519
|
+
VALUE pycall_without_gvl(VALUE (* func)(VALUE), VALUE arg);
|
|
520
|
+
|
|
495
521
|
/* ==== pycall ==== */
|
|
496
522
|
|
|
497
523
|
typedef struct {
|
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
|
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
|
@@ -27,12 +27,12 @@ module PyCall
|
|
|
27
27
|
def find_python_config(python = nil)
|
|
28
28
|
python ||= DEFAULT_PYTHON
|
|
29
29
|
Array(python).each do |python_cmd|
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
begin
|
|
31
|
+
python_config = investigate_python_config(python_cmd)
|
|
32
|
+
return [python_cmd, python_config] unless python_config.empty?
|
|
33
|
+
rescue
|
|
34
|
+
end
|
|
32
35
|
end
|
|
33
|
-
rescue
|
|
34
|
-
raise ::PyCall::PythonNotFound
|
|
35
|
-
else
|
|
36
36
|
raise ::PyCall::PythonNotFound
|
|
37
37
|
end
|
|
38
38
|
|
|
@@ -40,10 +40,6 @@ module PyCall
|
|
|
40
40
|
debug_report("find_libpython(#{python.inspect})")
|
|
41
41
|
python, python_config = find_python_config(python)
|
|
42
42
|
|
|
43
|
-
set_PYTHONHOME(python_config)
|
|
44
|
-
libs = make_libs(python_config)
|
|
45
|
-
libpaths = make_libpaths(python_config)
|
|
46
|
-
|
|
47
43
|
# Try LIBPYTHON environment variable first.
|
|
48
44
|
if (libpython = ENV['LIBPYTHON'])
|
|
49
45
|
if File.file?(libpython)
|
|
@@ -59,6 +55,9 @@ module PyCall
|
|
|
59
55
|
end
|
|
60
56
|
|
|
61
57
|
# Find libpython (we hope):
|
|
58
|
+
set_PYTHONHOME(python_config)
|
|
59
|
+
libs = make_libs(python_config)
|
|
60
|
+
libpaths = make_libpaths(python_config)
|
|
62
61
|
multiarch = python_config[:MULTIARCH] || python_config[:multiarch]
|
|
63
62
|
libs.each do |lib|
|
|
64
63
|
libpaths.each do |libpath|
|
|
@@ -121,7 +120,7 @@ module PyCall
|
|
|
121
120
|
end
|
|
122
121
|
|
|
123
122
|
def set_PYTHONHOME(python_config)
|
|
124
|
-
if !ENV.has_key?('PYTHONHOME')
|
|
123
|
+
if !ENV.has_key?('PYTHONHOME')
|
|
125
124
|
case RUBY_PLATFORM
|
|
126
125
|
when /mingw32/, /cygwin/, /mswin/
|
|
127
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)))
|
|
@@ -51,8 +51,18 @@ module PyCall
|
|
|
51
51
|
|
|
52
52
|
def <(other)
|
|
53
53
|
case other
|
|
54
|
+
when self
|
|
55
|
+
false
|
|
54
56
|
when PyTypeObjectWrapper
|
|
55
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
|
|
56
66
|
else
|
|
57
67
|
raise TypeError, "compared with non class/module"
|
|
58
68
|
end
|
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
|
|
|
@@ -30,11 +36,11 @@ Gem::Specification.new do |spec|
|
|
|
30
36
|
spec.require_paths = ["lib"]
|
|
31
37
|
spec.extensions = ["ext/pycall/extconf.rb"]
|
|
32
38
|
|
|
33
|
-
spec.add_development_dependency "bundler"
|
|
34
|
-
spec.add_development_dependency "rake"
|
|
39
|
+
spec.add_development_dependency "bundler"
|
|
40
|
+
spec.add_development_dependency "rake"
|
|
35
41
|
spec.add_development_dependency "rake-compiler"
|
|
36
42
|
spec.add_development_dependency "rake-compiler-dock"
|
|
37
|
-
spec.add_development_dependency "rspec"
|
|
43
|
+
spec.add_development_dependency "rspec"
|
|
38
44
|
spec.add_development_dependency "launchy"
|
|
39
45
|
spec.add_development_dependency "pry"
|
|
40
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"
|
|
@@ -171,6 +172,7 @@ files:
|
|
|
171
172
|
- ext/pycall/pycall_internal.h
|
|
172
173
|
- ext/pycall/range.c
|
|
173
174
|
- ext/pycall/ruby_wrapper.c
|
|
175
|
+
- ext/pycall/thread.c
|
|
174
176
|
- images/pycallrb_logo.png
|
|
175
177
|
- images/pycallrb_logo_200.png
|
|
176
178
|
- lib/pycall.rb
|
|
@@ -187,6 +189,7 @@ files:
|
|
|
187
189
|
- lib/pycall/list.rb
|
|
188
190
|
- lib/pycall/pretty_print.rb
|
|
189
191
|
- lib/pycall/pyerror.rb
|
|
192
|
+
- lib/pycall/pymodule_wrapper.rb
|
|
190
193
|
- lib/pycall/pyobject_wrapper.rb
|
|
191
194
|
- lib/pycall/python/PyCall/__init__.py
|
|
192
195
|
- lib/pycall/python/PyCall/six.py
|
|
@@ -214,12 +217,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
214
217
|
version: '0'
|
|
215
218
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
216
219
|
requirements:
|
|
217
|
-
- - "
|
|
220
|
+
- - ">="
|
|
218
221
|
- !ruby/object:Gem::Version
|
|
219
|
-
version:
|
|
222
|
+
version: '0'
|
|
220
223
|
requirements: []
|
|
221
|
-
|
|
222
|
-
rubygems_version: 2.7.6
|
|
224
|
+
rubygems_version: 3.1.2
|
|
223
225
|
signing_key:
|
|
224
226
|
specification_version: 4
|
|
225
227
|
summary: pycall
|