pycall 1.5.2 → 1.5.3
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/dependabot.yml +7 -8
- data/.github/workflows/ci.yml +23 -25
- data/.github/workflows/release.yml +48 -0
- data/.github/workflows/windows.yml +18 -17
- data/CHANGES.md +10 -0
- data/README.md +20 -46
- data/Rakefile +11 -0
- data/docker/Dockerfile +1 -1
- data/ext/pycall/pycall.c +118 -10
- data/ext/pycall/pycall_internal.h +2 -1
- data/ext/pycall/ruby_wrapper.c +5 -69
- data/lib/pycall/libpython/pytypeobject_struct.rb +1 -1
- data/lib/pycall/pyobject_wrapper.rb +2 -3
- data/lib/pycall/version.rb +1 -1
- data/lib/pycall.rb +1 -1
- data/pycall.gemspec +7 -15
- metadata +15 -36
- data/bin/guard +0 -17
- data/ci/travis_before_script.sh +0 -21
- data/ci/travis_install.sh +0 -69
- data/ci/travis_retry.sh +0 -19
- data/config/Guardfile +0 -30
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cbe8667d161e27770570029b6e2da005db45d5f2e61482ba7ffa96117fa82a61
|
|
4
|
+
data.tar.gz: 530c510c0accfc3b1af1daf69ad530855ecf943ffaf6dd9d47975bf7f89132a7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 179af9a8a76e9f4528990468e8eb776c9031390cea2f28219c3da8aaf5dbc017df1cf2dfdf254b549a9313800ec640f82d4ca5302d6b74d3b192cc79daaf896b
|
|
7
|
+
data.tar.gz: 71a248181b886b513a650aef95a583563d5bb34e125e8f0bc1dc838e47c8ab6d38480bfe77d017065c73c47177dccab6d5a27b28d666b401e325fb118e95ea30
|
data/.github/dependabot.yml
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
# To get started with Dependabot version updates, you'll need to specify which
|
|
2
|
-
# package ecosystems to update and where the package manifests are located.
|
|
3
|
-
# Please see the documentation for all configuration options:
|
|
4
|
-
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
|
5
|
-
|
|
6
1
|
version: 2
|
|
7
2
|
updates:
|
|
8
|
-
- package-ecosystem: "
|
|
9
|
-
directory: "/"
|
|
3
|
+
- package-ecosystem: "github-actions"
|
|
4
|
+
directory: "/"
|
|
10
5
|
schedule:
|
|
11
|
-
interval: "
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
- package-ecosystem: "bundler"
|
|
8
|
+
directory: "/"
|
|
9
|
+
schedule:
|
|
10
|
+
interval: "weekly"
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -3,14 +3,9 @@ name: CI
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
5
|
branches:
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
- "check/unix/**"
|
|
6
|
+
- "**"
|
|
7
|
+
- '!dependabot/**'
|
|
9
8
|
pull_request:
|
|
10
|
-
types:
|
|
11
|
-
- opened
|
|
12
|
-
- synchronize
|
|
13
|
-
- reopened
|
|
14
9
|
|
|
15
10
|
jobs:
|
|
16
11
|
test:
|
|
@@ -22,9 +17,10 @@ jobs:
|
|
|
22
17
|
matrix:
|
|
23
18
|
os:
|
|
24
19
|
- ubuntu-latest
|
|
25
|
-
- ubuntu-
|
|
20
|
+
- ubuntu-22.04
|
|
26
21
|
- macos-latest
|
|
27
22
|
ruby:
|
|
23
|
+
- "3.4"
|
|
28
24
|
- "3.3"
|
|
29
25
|
- "3.2"
|
|
30
26
|
- "3.1"
|
|
@@ -37,25 +33,27 @@ jobs:
|
|
|
37
33
|
venv:
|
|
38
34
|
- ""
|
|
39
35
|
include:
|
|
36
|
+
# Python 3.11 with the latest Ruby
|
|
37
|
+
- { os: ubuntu-22.04 , ruby: 3.3 , python: "3.11" , python_architecture: x64 , venv: "" }
|
|
38
|
+
|
|
40
39
|
# Old ruby and the latest Python 3
|
|
41
|
-
- { os: ubuntu-
|
|
42
|
-
- { os: ubuntu-
|
|
43
|
-
- { os: ubuntu-
|
|
40
|
+
- { os: ubuntu-22.04 , ruby: 2.6 , python: "3.x" , python_architecture: x64 , venv: "" }
|
|
41
|
+
- { os: ubuntu-22.04 , ruby: 2.5 , python: "3.x" , python_architecture: x64 , venv: "" }
|
|
42
|
+
- { os: ubuntu-22.04 , ruby: 2.4 , python: "3.x" , python_architecture: x64 , venv: "" }
|
|
44
43
|
|
|
45
44
|
# Ruby 2.7 with Each Python 3.x
|
|
46
|
-
- { os: ubuntu-
|
|
47
|
-
- { os: ubuntu-
|
|
48
|
-
- { os: ubuntu-
|
|
49
|
-
- { os: ubuntu-
|
|
50
|
-
- { os: ubuntu-
|
|
51
|
-
- { os: ubuntu-
|
|
52
|
-
- { os: ubuntu-20.04 , ruby: 2.7 , python: "3.6" , python_architecture: x64 , venv: "" }
|
|
45
|
+
- { os: ubuntu-22.04 , ruby: 2.7 , python: "3.12" , python_architecture: x64 , venv: "" }
|
|
46
|
+
- { os: ubuntu-22.04 , ruby: 2.7 , python: "3.11" , python_architecture: x64 , venv: "" }
|
|
47
|
+
- { os: ubuntu-22.04 , ruby: 2.7 , python: "3.10" , python_architecture: x64 , venv: "" }
|
|
48
|
+
- { os: ubuntu-22.04 , ruby: 2.7 , python: "3.9" , python_architecture: x64 , venv: "" }
|
|
49
|
+
- { os: ubuntu-22.04 , ruby: 2.7 , python: "3.8" , python_architecture: x64 , venv: "" }
|
|
50
|
+
- { os: ubuntu-22.04 , ruby: 2.7 , python: "3.7" , python_architecture: x64 , venv: "" }
|
|
53
51
|
|
|
54
52
|
# Ruby-debug with the latest Python 3
|
|
55
|
-
- { os: ubuntu-
|
|
53
|
+
- { os: ubuntu-22.04 , ruby: debug , python: "3.x" , python_architecture: x64 , venv: "" }
|
|
56
54
|
|
|
57
55
|
# The latest stable Ruby with the latest Python 3 with venv
|
|
58
|
-
- { os: ubuntu-
|
|
56
|
+
- { os: ubuntu-22.04 , ruby: "3.3" , python: "3.x" , python_architecture: x64 , venv: "venv:" }
|
|
59
57
|
|
|
60
58
|
# macOS with venv
|
|
61
59
|
- { os: macos-latest , ruby: "3.3" , python: "3.x" , python_architecture: x64 , venv: "venv:" }
|
|
@@ -63,7 +61,7 @@ jobs:
|
|
|
63
61
|
#- { os: macos-latest , ruby: debug , python: "3.x" , python_architecture: x64 , venv: "" }
|
|
64
62
|
|
|
65
63
|
steps:
|
|
66
|
-
- uses: actions/checkout@
|
|
64
|
+
- uses: actions/checkout@v7
|
|
67
65
|
with:
|
|
68
66
|
fetch-depth: 1
|
|
69
67
|
|
|
@@ -72,7 +70,7 @@ jobs:
|
|
|
72
70
|
with:
|
|
73
71
|
ruby-version: ${{ matrix.ruby }}
|
|
74
72
|
|
|
75
|
-
- uses: actions/setup-python@
|
|
73
|
+
- uses: actions/setup-python@v7
|
|
76
74
|
with:
|
|
77
75
|
python-version: ${{ matrix.python }}
|
|
78
76
|
architecture: ${{ matrix.python_architecture }}
|
|
@@ -106,7 +104,7 @@ jobs:
|
|
|
106
104
|
fail-fast: false
|
|
107
105
|
matrix:
|
|
108
106
|
os:
|
|
109
|
-
- ubuntu-
|
|
107
|
+
- ubuntu-22.04
|
|
110
108
|
#- macos-latest
|
|
111
109
|
ruby:
|
|
112
110
|
- "3.1"
|
|
@@ -114,11 +112,11 @@ jobs:
|
|
|
114
112
|
- "3.10"
|
|
115
113
|
|
|
116
114
|
steps:
|
|
117
|
-
- uses: actions/checkout@
|
|
115
|
+
- uses: actions/checkout@v7
|
|
118
116
|
with:
|
|
119
117
|
fetch-depth: 1
|
|
120
118
|
|
|
121
|
-
- uses: conda-incubator/setup-miniconda@
|
|
119
|
+
- uses: conda-incubator/setup-miniconda@v4
|
|
122
120
|
with:
|
|
123
121
|
activate-environment: test
|
|
124
122
|
python-version: ${{ matrix.python }}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
tags:
|
|
5
|
+
- "*"
|
|
6
|
+
jobs:
|
|
7
|
+
github:
|
|
8
|
+
name: GitHub
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
timeout-minutes: 10
|
|
11
|
+
permissions:
|
|
12
|
+
contents: write
|
|
13
|
+
discussions: write
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v7
|
|
16
|
+
- name: Extract release note
|
|
17
|
+
run: |
|
|
18
|
+
ruby \
|
|
19
|
+
-e 'print("## PyCall "); \
|
|
20
|
+
puts(ARGF.read.split(/^## /)[1])' \
|
|
21
|
+
CHANGES.md > release-note.md
|
|
22
|
+
- name: Upload to release
|
|
23
|
+
env:
|
|
24
|
+
GH_TOKEN: ${{ github.token }}
|
|
25
|
+
run: |
|
|
26
|
+
title=$(head -n1 release-note.md | sed -e 's/^## //')
|
|
27
|
+
tail -n +2 release-note.md > release-note-without-version.md
|
|
28
|
+
gh release create ${GITHUB_REF_NAME} \
|
|
29
|
+
--discussion-category Announcements \
|
|
30
|
+
--notes-file release-note-without-version.md \
|
|
31
|
+
--title "${title}"
|
|
32
|
+
rubygems:
|
|
33
|
+
name: RubyGems
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
timeout-minutes: 10
|
|
36
|
+
permissions:
|
|
37
|
+
id-token: write
|
|
38
|
+
environment: release
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/checkout@v7
|
|
41
|
+
- uses: ruby/setup-ruby@v1
|
|
42
|
+
with:
|
|
43
|
+
ruby-version: ruby
|
|
44
|
+
bundler-cache: true
|
|
45
|
+
- uses: rubygems/configure-rubygems-credentials@v2.1.0
|
|
46
|
+
- name: Push gems
|
|
47
|
+
run: |
|
|
48
|
+
bundle exec rake release:rubygem_push
|
|
@@ -3,14 +3,9 @@ name: Windows
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
5
|
branches:
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
- "check/windows/**"
|
|
6
|
+
- "**"
|
|
7
|
+
- '!dependabot/**'
|
|
9
8
|
pull_request:
|
|
10
|
-
types:
|
|
11
|
-
- opened
|
|
12
|
-
- synchronize
|
|
13
|
-
- reopened
|
|
14
9
|
|
|
15
10
|
jobs:
|
|
16
11
|
test:
|
|
@@ -21,19 +16,24 @@ jobs:
|
|
|
21
16
|
fail-fast: false
|
|
22
17
|
matrix:
|
|
23
18
|
ruby:
|
|
19
|
+
- "3.3"
|
|
20
|
+
- "3.2"
|
|
21
|
+
- "3.1"
|
|
24
22
|
- "3.0"
|
|
25
|
-
- 2.7
|
|
26
|
-
- 2.6
|
|
23
|
+
- "2.7"
|
|
27
24
|
python:
|
|
28
25
|
- 3.x
|
|
29
26
|
python_architecture:
|
|
30
27
|
- x64
|
|
31
28
|
include:
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
# Python 3.11 with the latest Ruby
|
|
30
|
+
- { ruby: "3.3" , python: 3.11 , python_architecture: x64 }
|
|
31
|
+
# The development version of Ruby
|
|
32
|
+
- { ruby: mingw , python: 3.x , python_architecture: x64 }
|
|
33
|
+
#- { ruby: mswin , python: 3.x , python_architecture: x64 }
|
|
34
34
|
|
|
35
35
|
steps:
|
|
36
|
-
- uses: actions/checkout@
|
|
36
|
+
- uses: actions/checkout@v7
|
|
37
37
|
with:
|
|
38
38
|
fetch-depth: 1
|
|
39
39
|
|
|
@@ -42,7 +42,7 @@ jobs:
|
|
|
42
42
|
with:
|
|
43
43
|
ruby-version: ${{ matrix.ruby }}
|
|
44
44
|
|
|
45
|
-
- uses: actions/setup-python@
|
|
45
|
+
- uses: actions/setup-python@v7
|
|
46
46
|
with:
|
|
47
47
|
python-version: ${{ matrix.python }}
|
|
48
48
|
architecture: ${{ matrix.python_architecture }}
|
|
@@ -67,20 +67,21 @@ jobs:
|
|
|
67
67
|
fail-fast: false
|
|
68
68
|
matrix:
|
|
69
69
|
ruby:
|
|
70
|
-
- "3.
|
|
70
|
+
- "3.3"
|
|
71
71
|
python:
|
|
72
|
-
- 3.
|
|
72
|
+
- 3.12
|
|
73
|
+
- 3.11
|
|
73
74
|
|
|
74
75
|
defaults:
|
|
75
76
|
run:
|
|
76
77
|
shell: pwsh
|
|
77
78
|
|
|
78
79
|
steps:
|
|
79
|
-
- uses: actions/checkout@
|
|
80
|
+
- uses: actions/checkout@v7
|
|
80
81
|
with:
|
|
81
82
|
fetch-depth: 1
|
|
82
83
|
|
|
83
|
-
- uses: conda-incubator/setup-miniconda@
|
|
84
|
+
- uses: conda-incubator/setup-miniconda@v4
|
|
84
85
|
with:
|
|
85
86
|
activate-environment: test
|
|
86
87
|
python-version: ${{ matrix.python }}
|
data/CHANGES.md
CHANGED
data/README.md
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
# PyCall: Calling Python functions from the Ruby language
|
|
7
7
|
|
|
8
|
-
[](https://ci.appveyor.com/project/mrkn/pycall-rb/branch/master)
|
|
8
|
+
[](https://github.com/red-data-tools/pycall.rb/actions?query=workflow%3ACI)
|
|
10
9
|
|
|
11
10
|
This library provides the features to directly call and partially interoperate
|
|
12
11
|
with Python from the Ruby language. You can import arbitrary Python modules
|
|
@@ -21,6 +20,10 @@ pycall.rb supports Ruby version 2.4 or higher.
|
|
|
21
20
|
|
|
22
21
|
pycall.rb supports Python version 3.7 or higher.
|
|
23
22
|
|
|
23
|
+
## PyCall does not support multi-threaded use officially
|
|
24
|
+
|
|
25
|
+
CPython's C-API has GIL acquiring/releasing functions such as `PyGILState_Ensure` and `PyGILState_Release`. Programmers can call CPython's C-APIs from outside of Python threads if they manage GIL's state by these functions. However, we do not want to officially support the multi-threaded use of PyCall because creating the feature enabling stable multi-threaded use in any situation is too difficult. We want to avoid incurring the costs to support such use cases.
|
|
26
|
+
|
|
24
27
|
## Note for pyenv users
|
|
25
28
|
|
|
26
29
|
pycall.rb requires Python's shared library (e.g. `libpython3.7m.so`).
|
|
@@ -128,15 +131,15 @@ DEBUG(find_libpython) dlopen("/opt/brew/opt/python/Frameworks/Python.framework/V
|
|
|
128
131
|
|
|
129
132
|
### matplotlib
|
|
130
133
|
|
|
131
|
-
Use [
|
|
134
|
+
Use [red-data-tools/matplotlib.rb](https://github.com/red-data-tools/matplotlib.rb) instead of just importing it by `PyCall.import_module("matplotlib")`.
|
|
132
135
|
|
|
133
136
|
### numpy
|
|
134
137
|
|
|
135
|
-
Use [
|
|
138
|
+
Use [red-data-tools/numpy.rb](https://github.com/red-data-tools/numpy.rb) instead of just importing it by `PyCall.import_module("numpy")`.
|
|
136
139
|
|
|
137
140
|
### pandas
|
|
138
141
|
|
|
139
|
-
Use [
|
|
142
|
+
Use [red-data-tools/pandas.rb](https://github.com/red-data-tools/pandas.rb) instead of just importing it by `PyCall.import_module("pandas")`.
|
|
140
143
|
|
|
141
144
|
## PyCall object system
|
|
142
145
|
|
|
@@ -159,41 +162,16 @@ translates Ruby's coerce system into Python's swapped operation protocol.
|
|
|
159
162
|
|
|
160
163
|
## Deploying on Heroku
|
|
161
164
|
|
|
162
|
-
Heroku's default
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
There are many ways to make our heroku use Python that is compiled with the `--enabled-shared` option:
|
|
166
|
-
|
|
167
|
-
- use Heroku's official Python buildpacks `post_compile` hooks to recompile the python if the `--enabled-shared` option is not enabled.
|
|
168
|
-
example script of `post_compile` in ruby on rails app `bin/post_compile`.
|
|
169
|
-
|
|
170
|
-
set -e
|
|
171
|
-
buildpack_url=https://github.com/heroku/heroku-buildpack-python
|
|
172
|
-
buildpack_vsn=v197 # adjust version accordingly https://github.com/heroku/heroku-buildpack-python/tags
|
|
165
|
+
Heroku's default builds of Python are now compiled with the `--enabled-shared` option
|
|
166
|
+
(when using Python 3.10 and newer) and so work out of the box with PyCall without
|
|
167
|
+
the need for a custom buildpack.
|
|
173
168
|
|
|
174
|
-
|
|
175
|
-
if ! python3 -msysconfig | grep enable-shared \
|
|
176
|
-
> /dev/null; then
|
|
177
|
-
PYTHON_VERSION="$(< runtime.txt)"
|
|
178
|
-
git clone -b "$buildpack_vsn" "$buildpack_url" _buildpack
|
|
179
|
-
export WORKSPACE_DIR="$PWD/_buildpack/builds"
|
|
180
|
-
rm -f .heroku/python/bin/python # prevent failing ln after build
|
|
181
|
-
sed -i 's!figure --pre!figure --enable-shared --pre!' \
|
|
182
|
-
"$WORKSPACE_DIR"/runtimes/python3
|
|
183
|
-
"$WORKSPACE_DIR/runtimes/$PYTHON_VERSION" /app/.heroku/python/
|
|
184
|
-
rm -fr _buildpack
|
|
185
|
-
fi
|
|
186
|
-
|
|
187
|
-
- use your own precompiled python with `--enabled-shared` options then fork the official heroku [python buildspacks](https://github.com/heroku/heroku-buildpack-python) and change the `BUILDPACK_S3_BASE_URL` with your own uploaded precompiled python in Amazon's S3.
|
|
188
|
-
- use 3rd party buildpacks from the [markets](https://elements.heroku.com/buildpacks) that have python with `--enabled-shared` option.
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
The buildpack will expect to find both a `runtime.txt` and a `requirements.txt`
|
|
169
|
+
The Python buildpack will expect to find both a `.python-version` and a `requirements.txt`
|
|
192
170
|
file in the root of your project. You will need to add these to specify the
|
|
193
171
|
version of Python and any packages to be installed via `pip`, _e.g_ to use
|
|
194
|
-
version Python 3.
|
|
172
|
+
the latest patch version Python 3.12 and version 2.5 of the 'networkx' package:
|
|
195
173
|
|
|
196
|
-
$ echo "
|
|
174
|
+
$ echo "3.12" > .python-version
|
|
197
175
|
$ echo "networkx==2.5" >> requirements.txt
|
|
198
176
|
|
|
199
177
|
Commit these two files into project's repository. You'll use these to manage
|
|
@@ -212,12 +190,11 @@ For a Ruby/Rails application this will typically report the stock `heroku/ruby`
|
|
|
212
190
|
buildpack, or possibly both `heroku/ruby` and `heroku/nodejs`.
|
|
213
191
|
|
|
214
192
|
Clear the list and progressively add back your buildpacks, starting with the Python
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
be similar to this:
|
|
193
|
+
buildpack. For example, if `ruby` and `nodejs` buildpacks were previously installed,
|
|
194
|
+
your setup process will be similar to this:
|
|
218
195
|
|
|
219
196
|
$ heroku buildpacks:clear
|
|
220
|
-
$ heroku buildpacks:add
|
|
197
|
+
$ heroku buildpacks:add heroku/python -i 1
|
|
221
198
|
$ heroku buildpacks:add heroku/nodejs -i 2
|
|
222
199
|
# heroku buildpacks:add heroku/ruby -i 3
|
|
223
200
|
|
|
@@ -229,15 +206,12 @@ specify the order Heroku will load runtimes and execute bootstrapping code. It's
|
|
|
229
206
|
important for the Python environment to be engaged first, as PyCall will need to
|
|
230
207
|
be able to find it when Ruby-based processes start.
|
|
231
208
|
|
|
232
|
-
Once you have set up your buildpacks, and have
|
|
233
|
-
`
|
|
209
|
+
Once you have set up your buildpacks, and have committed both `requirements.txt` and
|
|
210
|
+
`.python-version` files to git, deploy your Heroku application as your normally would.
|
|
234
211
|
The Python bootstrapping process will appear in the log first, followed by the Ruby
|
|
235
212
|
and so on. PyCall should now be able to successfully call Python functions from
|
|
236
213
|
within the Heroku environment.
|
|
237
214
|
|
|
238
|
-
NB It is also possible to specify buildpacks within Docker images on Heroku.
|
|
239
|
-
See Heroku's [documentation on using Docker Images](https://devcenter.heroku.com/articles/build-docker-images-heroku-yml).
|
|
240
|
-
|
|
241
215
|
## Development
|
|
242
216
|
|
|
243
217
|
After checking out the repo, run `bin/setup` to install dependencies.
|
|
@@ -253,7 +227,7 @@ version, push git commits and tags, and push the `.gem` file to
|
|
|
253
227
|
## Contributing
|
|
254
228
|
|
|
255
229
|
Bug reports and pull requests are welcome on GitHub at
|
|
256
|
-
https://github.com/
|
|
230
|
+
https://github.com/red-data-tools/pycall.rb.
|
|
257
231
|
|
|
258
232
|
|
|
259
233
|
## Acknowledgement
|
data/Rakefile
CHANGED
|
@@ -91,3 +91,14 @@ end
|
|
|
91
91
|
|
|
92
92
|
task default: :spec
|
|
93
93
|
task spec: :compile
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
release_task = Rake.application["release"]
|
|
97
|
+
# We use Trusted Publishing.
|
|
98
|
+
release_task.prerequisites.delete("build")
|
|
99
|
+
release_task.prerequisites.delete("release:rubygem_push")
|
|
100
|
+
release_task_comment = release_task.comment
|
|
101
|
+
if release_task_comment
|
|
102
|
+
release_task.clear_comments
|
|
103
|
+
release_task.comment = release_task_comment.gsub(/ and build.*$/, "")
|
|
104
|
+
end
|
data/docker/Dockerfile
CHANGED
|
@@ -183,7 +183,7 @@ RUN bundle exec iruby register
|
|
|
183
183
|
|
|
184
184
|
# Deploy matplotlib's examples
|
|
185
185
|
RUN mkdir -p /tmp \
|
|
186
|
-
&& curl -fsSL https://github.com/
|
|
186
|
+
&& curl -fsSL https://github.com/red-data-tools/matplotlib.rb/archive/master.tar.gz | tar -xzf - -C /tmp \
|
|
187
187
|
&& mv /tmp/matplotlib.rb-master/examples /notebooks/examples/matplotlib \
|
|
188
188
|
&& rm -rf /tmp/matplotlib.rb-master
|
|
189
189
|
|
data/ext/pycall/pycall.c
CHANGED
|
@@ -29,7 +29,6 @@ static int python_major_version;
|
|
|
29
29
|
static int python_has_stackless_extension;
|
|
30
30
|
static PyObject *python_builtins_module;
|
|
31
31
|
static VALUE python_type_mapping;
|
|
32
|
-
static VALUE python_type_mapping;
|
|
33
32
|
static ID id_python_type_mapping;
|
|
34
33
|
|
|
35
34
|
int
|
|
@@ -122,6 +121,58 @@ pycall_m_without_gvl(VALUE mod)
|
|
|
122
121
|
|
|
123
122
|
/* ==== PyCall::PyPtr ==== */
|
|
124
123
|
|
|
124
|
+
struct pending_decref_list {
|
|
125
|
+
rb_nativethread_lock_t lock;
|
|
126
|
+
PyObject **pyptrs;
|
|
127
|
+
size_t count;
|
|
128
|
+
size_t capacity;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
static struct pending_decref_list pending_decrefs;
|
|
132
|
+
|
|
133
|
+
static void
|
|
134
|
+
pycall_pending_decref_add(PyObject *pyobj)
|
|
135
|
+
{
|
|
136
|
+
rb_nativethread_lock_lock(&pending_decrefs.lock);
|
|
137
|
+
if (pending_decrefs.count == pending_decrefs.capacity) {
|
|
138
|
+
size_t new_capacity = pending_decrefs.capacity ? 2 * pending_decrefs.capacity : 64;
|
|
139
|
+
/* Not ruby_xrealloc: this function runs during GC, where xmalloc/xrealloc
|
|
140
|
+
* are prohibited (rb_bug "Cannot realloc during GC" since Ruby 3.3). */
|
|
141
|
+
PyObject **new_pyptrs = realloc(pending_decrefs.pyptrs, new_capacity * sizeof(PyObject *));
|
|
142
|
+
if (new_pyptrs == NULL) {
|
|
143
|
+
/* Leaking the object is preferable to blocking or crashing inside GC */
|
|
144
|
+
rb_nativethread_lock_unlock(&pending_decrefs.lock);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
pending_decrefs.pyptrs = new_pyptrs;
|
|
148
|
+
pending_decrefs.capacity = new_capacity;
|
|
149
|
+
}
|
|
150
|
+
pending_decrefs.pyptrs[pending_decrefs.count++] = pyobj;
|
|
151
|
+
rb_nativethread_lock_unlock(&pending_decrefs.lock);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
static void
|
|
155
|
+
pycall_drain_pending_decrefs(void)
|
|
156
|
+
{
|
|
157
|
+
PyObject **pyptrs;
|
|
158
|
+
size_t i, count;
|
|
159
|
+
|
|
160
|
+
if (pending_decrefs.count == 0) return;
|
|
161
|
+
|
|
162
|
+
rb_nativethread_lock_lock(&pending_decrefs.lock);
|
|
163
|
+
pyptrs = pending_decrefs.pyptrs;
|
|
164
|
+
count = pending_decrefs.count;
|
|
165
|
+
pending_decrefs.pyptrs = NULL;
|
|
166
|
+
pending_decrefs.count = 0;
|
|
167
|
+
pending_decrefs.capacity = 0;
|
|
168
|
+
rb_nativethread_lock_unlock(&pending_decrefs.lock);
|
|
169
|
+
|
|
170
|
+
for (i = 0; i < count; ++i) {
|
|
171
|
+
pycall_Py_DecRef(pyptrs[i]);
|
|
172
|
+
}
|
|
173
|
+
free(pyptrs);
|
|
174
|
+
}
|
|
175
|
+
|
|
125
176
|
const rb_data_type_t pycall_pyptr_data_type = {
|
|
126
177
|
"PyCall::PyPtr",
|
|
127
178
|
{ 0, pycall_pyptr_free, pycall_pyptr_memsize, },
|
|
@@ -130,6 +181,11 @@ const rb_data_type_t pycall_pyptr_data_type = {
|
|
|
130
181
|
#endif
|
|
131
182
|
};
|
|
132
183
|
|
|
184
|
+
/* pycall_pyptr_free may be called by the GC sweeper on a thread that does
|
|
185
|
+
* not hold the GIL. PyCall keeps the GIL held by the thread that
|
|
186
|
+
* initialized Python for the entire lifetime of the process, so waiting
|
|
187
|
+
* for the GIL there (PyGILState_Ensure) blocks forever while the sweeper
|
|
188
|
+
* holds the GVL, freezing every Ruby thread in the process. */
|
|
133
189
|
void
|
|
134
190
|
pycall_pyptr_free(void *ptr)
|
|
135
191
|
{
|
|
@@ -144,9 +200,9 @@ pycall_pyptr_free(void *ptr)
|
|
|
144
200
|
pycall_Py_DecRef(pyobj);
|
|
145
201
|
}
|
|
146
202
|
else {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
203
|
+
/* Instead of taking the GIL here, enqueue the pointer; the list is
|
|
204
|
+
* drained on the next Python call. */
|
|
205
|
+
pycall_pending_decref_add(pyobj);
|
|
150
206
|
}
|
|
151
207
|
}
|
|
152
208
|
|
|
@@ -628,6 +684,8 @@ pycall_libpython_api_PyObject_Dir(VALUE mod, VALUE pyptr)
|
|
|
628
684
|
PyObject *dir;
|
|
629
685
|
PyObject *pyobj;
|
|
630
686
|
|
|
687
|
+
pycall_drain_pending_decrefs();
|
|
688
|
+
|
|
631
689
|
if (!is_pycall_pyptr(pyptr)) {
|
|
632
690
|
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
|
633
691
|
}
|
|
@@ -647,6 +705,8 @@ pycall_libpython_api_PyList_Size(VALUE mod, VALUE pyptr)
|
|
|
647
705
|
PyObject *pyobj;
|
|
648
706
|
Py_ssize_t size;
|
|
649
707
|
|
|
708
|
+
pycall_drain_pending_decrefs();
|
|
709
|
+
|
|
650
710
|
if (!is_pycall_pyptr(pyptr)) {
|
|
651
711
|
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
|
652
712
|
}
|
|
@@ -667,6 +727,8 @@ pycall_libpython_api_PyList_GetItem(VALUE mod, VALUE pyptr, VALUE idx)
|
|
|
667
727
|
PyObject *pyobj_item;
|
|
668
728
|
Py_ssize_t i;
|
|
669
729
|
|
|
730
|
+
pycall_drain_pending_decrefs();
|
|
731
|
+
|
|
670
732
|
if (!is_pycall_pyptr(pyptr)) {
|
|
671
733
|
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
|
672
734
|
}
|
|
@@ -732,6 +794,8 @@ pycall_libpython_helpers_m_import_module(int argc, VALUE *argv, VALUE mod)
|
|
|
732
794
|
VALUE name, globals, locals, fromlist, level;
|
|
733
795
|
char const *name_cstr;
|
|
734
796
|
|
|
797
|
+
pycall_drain_pending_decrefs();
|
|
798
|
+
|
|
735
799
|
rb_scan_args(argc, argv, "14", &name, &globals, &locals, &fromlist, &level);
|
|
736
800
|
|
|
737
801
|
if (RB_TYPE_P(name, T_SYMBOL)) {
|
|
@@ -784,6 +848,8 @@ pycall_libpython_helpers_m_compare(VALUE mod, VALUE op, VALUE pyptr_a, VALUE pyp
|
|
|
784
848
|
PyObject *pyobj_a, *pyobj_b, *res;
|
|
785
849
|
int opid;
|
|
786
850
|
|
|
851
|
+
pycall_drain_pending_decrefs();
|
|
852
|
+
|
|
787
853
|
opid = pycall_rich_compare_opid(op);
|
|
788
854
|
|
|
789
855
|
if (!is_pycall_pyptr(pyptr_a)) {
|
|
@@ -838,6 +904,8 @@ pycall_libpython_helpers_m_getattr(int argc, VALUE *argv, VALUE mod)
|
|
|
838
904
|
{
|
|
839
905
|
VALUE pyptr, name, default_value;
|
|
840
906
|
|
|
907
|
+
pycall_drain_pending_decrefs();
|
|
908
|
+
|
|
841
909
|
if (rb_scan_args(argc, argv, "21", &pyptr, &name, &default_value) == 2) {
|
|
842
910
|
default_value = Qundef;
|
|
843
911
|
}
|
|
@@ -859,6 +927,8 @@ pycall_libpython_helpers_m_hasattr_p(VALUE mod, VALUE pyptr, VALUE name)
|
|
|
859
927
|
PyObject *pyobj;
|
|
860
928
|
int res;
|
|
861
929
|
|
|
930
|
+
pycall_drain_pending_decrefs();
|
|
931
|
+
|
|
862
932
|
if (!is_pycall_pyptr(pyptr)) {
|
|
863
933
|
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
|
864
934
|
}
|
|
@@ -878,6 +948,8 @@ pycall_libpython_helpers_m_setattr(VALUE mod, VALUE pyptr, VALUE name, VALUE val
|
|
|
878
948
|
{
|
|
879
949
|
PyObject *pyobj, *pyval;
|
|
880
950
|
|
|
951
|
+
pycall_drain_pending_decrefs();
|
|
952
|
+
|
|
881
953
|
if (!is_pycall_pyptr(pyptr)) {
|
|
882
954
|
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
|
883
955
|
}
|
|
@@ -901,6 +973,8 @@ pycall_libpython_helpers_m_delattr(VALUE mod, VALUE pyptr, VALUE name)
|
|
|
901
973
|
{
|
|
902
974
|
PyObject *pyobj;
|
|
903
975
|
|
|
976
|
+
pycall_drain_pending_decrefs();
|
|
977
|
+
|
|
904
978
|
if (!is_pycall_pyptr(pyptr)) {
|
|
905
979
|
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
|
906
980
|
}
|
|
@@ -924,6 +998,8 @@ pycall_libpython_helpers_m_callable_p(VALUE mod, VALUE pyptr)
|
|
|
924
998
|
PyObject *pyobj;
|
|
925
999
|
int res;
|
|
926
1000
|
|
|
1001
|
+
pycall_drain_pending_decrefs();
|
|
1002
|
+
|
|
927
1003
|
if (!is_pycall_pyptr(pyptr)) {
|
|
928
1004
|
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
|
929
1005
|
}
|
|
@@ -940,6 +1016,8 @@ pycall_libpython_helpers_m_call_object(int argc, VALUE *argv, VALUE mod)
|
|
|
940
1016
|
VALUE pyptr;
|
|
941
1017
|
PyObject *pyobj;
|
|
942
1018
|
|
|
1019
|
+
pycall_drain_pending_decrefs();
|
|
1020
|
+
|
|
943
1021
|
if (argc < 1) {
|
|
944
1022
|
rb_raise(rb_eArgError, "too few arguments (%d for >=1)", argc);
|
|
945
1023
|
}
|
|
@@ -1089,6 +1167,8 @@ pycall_pyobject_wrapper_wrapper_method(int argc, VALUE *argv, VALUE wrapper)
|
|
|
1089
1167
|
char *name_cstr;
|
|
1090
1168
|
PyObject *pyobj, *attr;
|
|
1091
1169
|
|
|
1170
|
+
pycall_drain_pending_decrefs();
|
|
1171
|
+
|
|
1092
1172
|
pyptr = rb_attr_get(wrapper, rb_intern("@__pyptr__"));
|
|
1093
1173
|
if (NIL_P(pyptr) || !is_pycall_pyptr(pyptr)) {
|
|
1094
1174
|
rb_raise(rb_eTypeError, "Wrong wrapper object is given");
|
|
@@ -1144,6 +1224,8 @@ pycall_libpython_helpers_m_define_wrapper_method(VALUE mod, VALUE wrapper, VALUE
|
|
|
1144
1224
|
PyObject *pyobj, *attr;
|
|
1145
1225
|
char *name_cstr;
|
|
1146
1226
|
|
|
1227
|
+
pycall_drain_pending_decrefs();
|
|
1228
|
+
|
|
1147
1229
|
pyptr = rb_attr_get(wrapper, rb_intern("@__pyptr__"));
|
|
1148
1230
|
if (NIL_P(pyptr) || !is_pycall_pyptr(pyptr)) {
|
|
1149
1231
|
rb_raise(rb_eTypeError, "Wrong wrapper object is given");
|
|
@@ -1191,10 +1273,10 @@ pycall_convert_index(VALUE index)
|
|
|
1191
1273
|
}
|
|
1192
1274
|
}
|
|
1193
1275
|
else if (rb_obj_is_kind_of(index, rb_cRange)) {
|
|
1194
|
-
pyobj = pycall_pyslice_from_ruby(index); /* New
|
|
1276
|
+
pyobj = pycall_pyslice_from_ruby(index); /* New reference */
|
|
1195
1277
|
}
|
|
1196
1278
|
else if (pycall_obj_is_step_range(index)) {
|
|
1197
|
-
pyobj = pycall_pyslice_from_ruby(index); /* New
|
|
1279
|
+
pyobj = pycall_pyslice_from_ruby(index); /* New reference */
|
|
1198
1280
|
}
|
|
1199
1281
|
else {
|
|
1200
1282
|
pyobj = pycall_pyobject_from_ruby(index); /* New reference */
|
|
@@ -1209,6 +1291,8 @@ pycall_libpython_helpers_m_getitem(VALUE mod, VALUE pyptr, VALUE key)
|
|
|
1209
1291
|
PyObject *pyobj, *pyobj_key, *pyobj_v;
|
|
1210
1292
|
VALUE obj;
|
|
1211
1293
|
|
|
1294
|
+
pycall_drain_pending_decrefs();
|
|
1295
|
+
|
|
1212
1296
|
if (!is_pycall_pyptr(pyptr)) {
|
|
1213
1297
|
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
|
1214
1298
|
}
|
|
@@ -1234,6 +1318,8 @@ pycall_libpython_helpers_m_setitem(VALUE mod, VALUE pyptr, VALUE key, VALUE v)
|
|
|
1234
1318
|
PyObject *pyobj, *pyobj_key, *pyobj_value;
|
|
1235
1319
|
int res;
|
|
1236
1320
|
|
|
1321
|
+
pycall_drain_pending_decrefs();
|
|
1322
|
+
|
|
1237
1323
|
pyobj = check_get_pyobj_ptr(pyptr, NULL);
|
|
1238
1324
|
pyobj_key = pycall_convert_index(key);
|
|
1239
1325
|
pyobj_value = pycall_pyobject_from_ruby(v);
|
|
@@ -1254,6 +1340,8 @@ pycall_libpython_helpers_m_delitem(VALUE mod, VALUE pyptr, VALUE key)
|
|
|
1254
1340
|
PyObject *pyobj, *pyobj_key;
|
|
1255
1341
|
int res;
|
|
1256
1342
|
|
|
1343
|
+
pycall_drain_pending_decrefs();
|
|
1344
|
+
|
|
1257
1345
|
pyobj = check_get_pyobj_ptr(pyptr, NULL);
|
|
1258
1346
|
pyobj_key = pycall_convert_index(key);
|
|
1259
1347
|
|
|
@@ -1271,6 +1359,8 @@ pycall_libpython_helpers_m_str(VALUE mod, VALUE pyptr)
|
|
|
1271
1359
|
{
|
|
1272
1360
|
PyObject *pyobj, *pyobj_str;
|
|
1273
1361
|
|
|
1362
|
+
pycall_drain_pending_decrefs();
|
|
1363
|
+
|
|
1274
1364
|
pyobj = check_get_pyobj_ptr(pyptr, NULL);
|
|
1275
1365
|
|
|
1276
1366
|
pyobj_str = Py_API(PyObject_Str)(pyobj);
|
|
@@ -1289,6 +1379,8 @@ pycall_libpython_helpers_m_dict_contains(VALUE mod, VALUE pyptr, VALUE key)
|
|
|
1289
1379
|
PyObject *pyobj, *pyobj_key;
|
|
1290
1380
|
int res;
|
|
1291
1381
|
|
|
1382
|
+
pycall_drain_pending_decrefs();
|
|
1383
|
+
|
|
1292
1384
|
pyobj = check_get_pyobj_ptr(pyptr, Py_API(PyDict_Type));
|
|
1293
1385
|
pyobj_key = pycall_pyobject_from_ruby(key);
|
|
1294
1386
|
res = Py_API(PyDict_Contains)(pyobj, pyobj_key);
|
|
@@ -1306,6 +1398,8 @@ pycall_libpython_helpers_m_dict_each(VALUE mod, VALUE pyptr)
|
|
|
1306
1398
|
PyObject *pyobj, *pyobj_key, *pyobj_value;
|
|
1307
1399
|
Py_ssize_t pos;
|
|
1308
1400
|
|
|
1401
|
+
pycall_drain_pending_decrefs();
|
|
1402
|
+
|
|
1309
1403
|
pyobj = check_get_pyobj_ptr(pyptr, Py_API(PyDict_Type));
|
|
1310
1404
|
|
|
1311
1405
|
pos = 0;
|
|
@@ -1325,6 +1419,8 @@ pycall_libpython_helpers_m_sequence_contains(VALUE mod, VALUE pyptr, VALUE key)
|
|
|
1325
1419
|
PyObject *pyobj, *pyobj_key;
|
|
1326
1420
|
int res;
|
|
1327
1421
|
|
|
1422
|
+
pycall_drain_pending_decrefs();
|
|
1423
|
+
|
|
1328
1424
|
pyobj = check_get_pyobj_ptr(pyptr, NULL);
|
|
1329
1425
|
if (!Py_API(PySequence_Check)(pyobj))
|
|
1330
1426
|
rb_raise(rb_eTypeError, "unexpected Python type %s (expected a Python sequence object)", Py_TYPE(pyobj)->tp_name);
|
|
@@ -1344,6 +1440,8 @@ pycall_libpython_helpers_m_sequence_each(VALUE mod, VALUE pyptr)
|
|
|
1344
1440
|
{
|
|
1345
1441
|
PyObject *pyobj, *pyobj_iter, *pyobj_item;
|
|
1346
1442
|
|
|
1443
|
+
pycall_drain_pending_decrefs();
|
|
1444
|
+
|
|
1347
1445
|
pyobj = check_get_pyobj_ptr(pyptr, NULL);
|
|
1348
1446
|
if (!Py_API(PySequence_Check)(pyobj))
|
|
1349
1447
|
rb_raise(rb_eTypeError, "unexpected Python type %s (expected a Python sequence object)", Py_TYPE(pyobj)->tp_name);
|
|
@@ -1528,7 +1626,7 @@ pycall_pyobject_to_ruby(PyObject *pyobj)
|
|
|
1528
1626
|
Py_API(Py_IncRef)((PyObject *)pyobj->ob_type);
|
|
1529
1627
|
cls = pycall_python_type_mapping_get_mapped_class(pycall_pytypeptr_new((PyObject *)pyobj->ob_type));
|
|
1530
1628
|
if (NIL_P(cls)) {
|
|
1531
|
-
rb_warning("
|
|
1629
|
+
rb_warning("Currently do not support to convert %s to Ruby object", Py_TYPE(pyobj)->tp_name);
|
|
1532
1630
|
return pycall_pyobject_wrapper_object_new(rb_cObject, pyobj);
|
|
1533
1631
|
}
|
|
1534
1632
|
|
|
@@ -1663,7 +1761,7 @@ pycall_pylong_to_ruby(PyObject *pyobj)
|
|
|
1663
1761
|
}
|
|
1664
1762
|
#endif
|
|
1665
1763
|
|
|
1666
|
-
rb_warning("
|
|
1764
|
+
rb_warning("Currently do not support to convert multi-precision PyLong number to Ruby object");
|
|
1667
1765
|
|
|
1668
1766
|
return Qnil;
|
|
1669
1767
|
}
|
|
@@ -1787,7 +1885,11 @@ pycall_conv_m_unregister_python_type_mapping(VALUE mod, VALUE pytypeptr)
|
|
|
1787
1885
|
static VALUE
|
|
1788
1886
|
pycall_conv_m_from_ruby(VALUE mod, VALUE obj)
|
|
1789
1887
|
{
|
|
1790
|
-
PyObject *pyobj
|
|
1888
|
+
PyObject *pyobj;
|
|
1889
|
+
|
|
1890
|
+
pycall_drain_pending_decrefs();
|
|
1891
|
+
|
|
1892
|
+
pyobj = pycall_pyobject_from_ruby(obj);
|
|
1791
1893
|
if (PyType_Check(pyobj) || PyClass_Check(pyobj))
|
|
1792
1894
|
return pycall_pytypeptr_new(pyobj);
|
|
1793
1895
|
if (PyRuby_Check(pyobj))
|
|
@@ -1799,7 +1901,11 @@ static VALUE
|
|
|
1799
1901
|
pycall_conv_m_to_ruby(VALUE mod, VALUE pyptr)
|
|
1800
1902
|
{
|
|
1801
1903
|
VALUE obj, obj_pyptr;
|
|
1802
|
-
PyObject *pyobj
|
|
1904
|
+
PyObject *pyobj;
|
|
1905
|
+
|
|
1906
|
+
pycall_drain_pending_decrefs();
|
|
1907
|
+
|
|
1908
|
+
pyobj = check_get_pyobj_ptr(pyptr, NULL);
|
|
1803
1909
|
obj = obj_pyptr = pycall_pyobject_to_ruby(pyobj);
|
|
1804
1910
|
if (is_pyobject_wrapper(obj)) {
|
|
1805
1911
|
obj_pyptr = pycall_pyobject_wrapper_get_pyptr(obj);
|
|
@@ -2321,6 +2427,8 @@ Init_pycall(void)
|
|
|
2321
2427
|
pycall_tls_create((pycall_tls_key *)&without_gvl_key);
|
|
2322
2428
|
rb_define_module_function(mPyCall, "without_gvl", pycall_m_without_gvl, 0);
|
|
2323
2429
|
|
|
2430
|
+
rb_nativethread_lock_initialize(&pending_decrefs.lock);
|
|
2431
|
+
|
|
2324
2432
|
/* PyCall::PyPtr */
|
|
2325
2433
|
|
|
2326
2434
|
cPyPtr = rb_define_class_under(mPyCall, "PyPtr", rb_cBasicObject);
|
|
@@ -11,6 +11,7 @@ extern "C" {
|
|
|
11
11
|
#include <ruby.h>
|
|
12
12
|
#include <ruby/encoding.h>
|
|
13
13
|
#include <ruby/thread.h>
|
|
14
|
+
#include <ruby/thread_native.h>
|
|
14
15
|
|
|
15
16
|
#include <assert.h>
|
|
16
17
|
#include <inttypes.h>
|
|
@@ -71,7 +72,7 @@ typedef intptr_t Py_intptr_t;
|
|
|
71
72
|
#ifdef HAVE_SSIZE_T
|
|
72
73
|
typedef ssize_t Py_ssize_t;
|
|
73
74
|
#elif SIZEOF_SIZE_T == SIZEOF_VOIDP
|
|
74
|
-
typedef
|
|
75
|
+
typedef Py_intptr_t Py_ssize_t;
|
|
75
76
|
#elif SIZEOF_SIZE_T == SIZEOF_INT
|
|
76
77
|
typedef int Py_ssize_t;
|
|
77
78
|
#elif SIZEOF_SIZE_T == SIZEOF_LONG
|
data/ext/pycall/ruby_wrapper.c
CHANGED
|
@@ -6,7 +6,6 @@ static PyMemberDef PyRuby_members[] = {
|
|
|
6
6
|
{NULL} /* sentinel */
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
-
static VALUE PyRuby_get_ruby_object_and_set_pyerr(PyObject *pyobj);
|
|
10
9
|
static void PyRuby_dealloc_with_gvl(PyRubyObject *);
|
|
11
10
|
static PyObject * PyRuby_repr_with_gvl(PyRubyObject *);
|
|
12
11
|
static PyObject * PyRuby_call_with_gvl(PyRubyObject *, PyObject *, PyObject *);
|
|
@@ -102,9 +101,7 @@ PyRuby_repr(PyRubyObject *pyro)
|
|
|
102
101
|
VALUE obj, str;
|
|
103
102
|
PyObject *res;
|
|
104
103
|
|
|
105
|
-
obj =
|
|
106
|
-
if (obj == Qundef)
|
|
107
|
-
return NULL;
|
|
104
|
+
obj = PyRuby_get_ruby_object((PyObject *)pyro);
|
|
108
105
|
|
|
109
106
|
str = rb_inspect(obj);
|
|
110
107
|
res = pycall_pystring_from_format("<PyCall.ruby_object %s>", StringValueCStr(str));
|
|
@@ -143,9 +140,7 @@ PyRuby_hash_long(PyRubyObject *pyro)
|
|
|
143
140
|
VALUE obj, rbhash;
|
|
144
141
|
intptr_t h;
|
|
145
142
|
|
|
146
|
-
obj =
|
|
147
|
-
if (obj == Qundef)
|
|
148
|
-
return (void *)-1;
|
|
143
|
+
obj = PyRuby_get_ruby_object((PyObject *)pyro);
|
|
149
144
|
|
|
150
145
|
rbhash = rb_hash(obj);
|
|
151
146
|
h = FIX2LONG(rbhash); /* Ruby's hash value is a Fixnum */
|
|
@@ -170,9 +165,7 @@ PyRuby_hash_hash_t(PyRubyObject *pyro)
|
|
|
170
165
|
VALUE obj, rbhash;
|
|
171
166
|
Py_hash_t h;
|
|
172
167
|
|
|
173
|
-
obj =
|
|
174
|
-
if (obj == Qundef)
|
|
175
|
-
return (void *)-1;
|
|
168
|
+
obj = PyRuby_get_ruby_object((PyObject *)pyro);
|
|
176
169
|
|
|
177
170
|
rbhash = rb_hash(obj);
|
|
178
171
|
#if SIZEOF_PY_HASH_T == SIZEOF_LONG
|
|
@@ -242,9 +235,7 @@ PyRuby_call(struct PyRuby_call_params *params)
|
|
|
242
235
|
PyObject *pyobj_res;
|
|
243
236
|
int state;
|
|
244
237
|
|
|
245
|
-
obj =
|
|
246
|
-
if (obj == Qundef)
|
|
247
|
-
return NULL;
|
|
238
|
+
obj = PyRuby_get_ruby_object((PyObject *)params->pyro);
|
|
248
239
|
|
|
249
240
|
id_call = rb_intern("call");
|
|
250
241
|
if (!rb_respond_to(obj, id_call)) {
|
|
@@ -296,9 +287,7 @@ PyRuby_getattro(struct PyRuby_getattro_params *params)
|
|
|
296
287
|
ID name_id;
|
|
297
288
|
PyObject *pyobj_res;
|
|
298
289
|
|
|
299
|
-
obj =
|
|
300
|
-
if (obj == Qundef)
|
|
301
|
-
return NULL;
|
|
290
|
+
obj = PyRuby_get_ruby_object((PyObject *)params->pyro);
|
|
302
291
|
|
|
303
292
|
name = pycall_pyobject_to_ruby(params->pyobj_name);
|
|
304
293
|
name_cstr = StringValueCStr(name);
|
|
@@ -489,56 +478,3 @@ pycall_init_ruby_wrapper(void)
|
|
|
489
478
|
rb_define_module_function(mPyCall, "wrap_ruby_object", pycall_m_wrap_ruby_object, 1);
|
|
490
479
|
}
|
|
491
480
|
|
|
492
|
-
/* --- File internal utilities --- */
|
|
493
|
-
|
|
494
|
-
static VALUE
|
|
495
|
-
funcall_id2ref(VALUE object_id)
|
|
496
|
-
{
|
|
497
|
-
VALUE rb_mObjSpace;
|
|
498
|
-
object_id = rb_check_to_integer(object_id, "to_int");
|
|
499
|
-
rb_mObjSpace = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
|
|
500
|
-
return rb_funcall(rb_mObjSpace, rb_intern("_id2ref"), 1, object_id);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
static VALUE
|
|
504
|
-
protect_id2ref(VALUE object_id)
|
|
505
|
-
{
|
|
506
|
-
VALUE obj;
|
|
507
|
-
int state;
|
|
508
|
-
|
|
509
|
-
obj = rb_protect((VALUE (*)(VALUE))funcall_id2ref, object_id, &state);
|
|
510
|
-
if (state)
|
|
511
|
-
return Qundef;
|
|
512
|
-
|
|
513
|
-
return obj;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
static VALUE
|
|
517
|
-
protect_id2ref_and_set_pyerr(VALUE object_id)
|
|
518
|
-
{
|
|
519
|
-
VALUE obj = protect_id2ref(object_id);
|
|
520
|
-
if (obj != Qundef)
|
|
521
|
-
return obj;
|
|
522
|
-
|
|
523
|
-
obj = rb_errinfo();
|
|
524
|
-
if (RTEST(rb_obj_is_kind_of(obj, rb_eRangeError))) {
|
|
525
|
-
Py_API(PyErr_SetString)(Py_API(PyExc_RuntimeError), "[BUG] referenced object was garbage-collected");
|
|
526
|
-
}
|
|
527
|
-
else {
|
|
528
|
-
VALUE emesg = rb_check_funcall(obj, rb_intern("message"), 0, 0);
|
|
529
|
-
Py_API(PyErr_Format)(Py_API(PyExc_RuntimeError),
|
|
530
|
-
"[BUG] Unable to obtain ruby object from ID: %s (%s)",
|
|
531
|
-
StringValueCStr(emesg), rb_class2name(CLASS_OF(obj)));
|
|
532
|
-
}
|
|
533
|
-
return Qundef;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
static VALUE
|
|
537
|
-
PyRuby_get_ruby_object_and_set_pyerr(PyObject *pyobj)
|
|
538
|
-
{
|
|
539
|
-
VALUE obj_id;
|
|
540
|
-
if (!PyRuby_Check(pyobj))
|
|
541
|
-
return Qundef;
|
|
542
|
-
obj_id = rb_obj_id(PyRuby_get_ruby_object(pyobj));
|
|
543
|
-
return protect_id2ref_and_set_pyerr(obj_id);
|
|
544
|
-
}
|
|
@@ -231,7 +231,7 @@ module PyCall
|
|
|
231
231
|
else
|
|
232
232
|
name, basic_size = *args
|
|
233
233
|
new.tap do |t|
|
|
234
|
-
# NOTE: Disable autorelease for avoiding SEGV
|
|
234
|
+
# NOTE: Disable autorelease for avoiding SEGV occurrence in Python's GC collect function
|
|
235
235
|
# at which the __new__ method object of this type object is freed.
|
|
236
236
|
t.pointer.autorelease = false
|
|
237
237
|
|
|
@@ -33,8 +33,6 @@ module PyCall
|
|
|
33
33
|
}.freeze
|
|
34
34
|
|
|
35
35
|
def method_missing(name, *args)
|
|
36
|
-
name_str = name.to_s if name.kind_of?(Symbol)
|
|
37
|
-
name_str.chop! if name_str.end_with?('=')
|
|
38
36
|
case name
|
|
39
37
|
when *OPERATOR_METHOD_NAMES.keys
|
|
40
38
|
op_name = OPERATOR_METHOD_NAMES[name]
|
|
@@ -44,7 +42,8 @@ module PyCall
|
|
|
44
42
|
return self.__send__(name, *args)
|
|
45
43
|
end
|
|
46
44
|
else
|
|
47
|
-
|
|
45
|
+
name_without_last_equal = name.to_s.chomp('=')
|
|
46
|
+
if LibPython::Helpers.hasattr?(__pyptr__, name_without_last_equal)
|
|
48
47
|
LibPython::Helpers.define_wrapper_method(self, name)
|
|
49
48
|
return self.__send__(name, *args)
|
|
50
49
|
end
|
data/lib/pycall/version.rb
CHANGED
data/lib/pycall.rb
CHANGED
|
@@ -116,7 +116,7 @@ module PyCall
|
|
|
116
116
|
rescue PyError => err
|
|
117
117
|
raise err unless ctx.__exit__(err.type, err.value, err.traceback)
|
|
118
118
|
rescue Exception => err
|
|
119
|
-
# TODO: support telling what exception has been
|
|
119
|
+
# TODO: support telling what exception has been caught
|
|
120
120
|
raise err unless ctx.__exit__(err.class, err, err.backtrace_locations)
|
|
121
121
|
else
|
|
122
122
|
ctx.__exit__(nil, nil, nil)
|
data/pycall.gemspec
CHANGED
|
@@ -1,29 +1,21 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
require 'pycall/version'
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/pycall/version'
|
|
5
4
|
|
|
6
5
|
Gem::Specification.new do |spec|
|
|
7
6
|
spec.name = "pycall"
|
|
8
|
-
|
|
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(".")
|
|
7
|
+
spec.version = PyCall::VERSION
|
|
15
8
|
spec.authors = ["Kenta Murata"]
|
|
16
9
|
spec.email = ["mrkn@mrkn.jp"]
|
|
17
10
|
|
|
18
11
|
spec.summary = %q{pycall}
|
|
19
12
|
spec.description = %q{pycall}
|
|
20
|
-
spec.homepage = "https://github.com/
|
|
13
|
+
spec.homepage = "https://github.com/red-data-tools/pycall.rb"
|
|
21
14
|
spec.license = "MIT"
|
|
22
15
|
|
|
23
16
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
24
17
|
case f
|
|
25
|
-
when %r{^
|
|
26
|
-
%r{^ext/pycall/spec_helper/},
|
|
18
|
+
when %r{^ext/pycall/spec_helper/},
|
|
27
19
|
%r{^(test|spec|features)/}
|
|
28
20
|
true
|
|
29
21
|
else
|
|
@@ -36,13 +28,13 @@ Gem::Specification.new do |spec|
|
|
|
36
28
|
spec.require_paths = ["lib"]
|
|
37
29
|
spec.extensions = ["ext/pycall/extconf.rb"]
|
|
38
30
|
|
|
31
|
+
spec.add_dependency 'fiddle', '>= 1.0.0'
|
|
32
|
+
|
|
39
33
|
spec.add_development_dependency "bundler"
|
|
40
34
|
spec.add_development_dependency "rake"
|
|
41
35
|
spec.add_development_dependency "rake-compiler"
|
|
42
36
|
spec.add_development_dependency "rake-compiler-dock"
|
|
43
37
|
spec.add_development_dependency "rspec"
|
|
44
38
|
spec.add_development_dependency "launchy"
|
|
45
|
-
spec.add_development_dependency "pry"
|
|
46
|
-
spec.add_development_dependency "pry-byebug"
|
|
47
39
|
spec.add_development_dependency "test-unit"
|
|
48
40
|
end
|
metadata
CHANGED
|
@@ -1,45 +1,30 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pycall
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.5.
|
|
4
|
+
version: 1.5.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kenta Murata
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - ">="
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0'
|
|
20
|
-
type: :development
|
|
21
|
-
prerelease: false
|
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
-
requirements:
|
|
24
|
-
- - ">="
|
|
25
|
-
- !ruby/object:Gem::Version
|
|
26
|
-
version: '0'
|
|
27
|
-
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: rake
|
|
13
|
+
name: fiddle
|
|
29
14
|
requirement: !ruby/object:Gem::Requirement
|
|
30
15
|
requirements:
|
|
31
16
|
- - ">="
|
|
32
17
|
- !ruby/object:Gem::Version
|
|
33
|
-
version:
|
|
34
|
-
type: :
|
|
18
|
+
version: 1.0.0
|
|
19
|
+
type: :runtime
|
|
35
20
|
prerelease: false
|
|
36
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
22
|
requirements:
|
|
38
23
|
- - ">="
|
|
39
24
|
- !ruby/object:Gem::Version
|
|
40
|
-
version:
|
|
25
|
+
version: 1.0.0
|
|
41
26
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
27
|
+
name: bundler
|
|
43
28
|
requirement: !ruby/object:Gem::Requirement
|
|
44
29
|
requirements:
|
|
45
30
|
- - ">="
|
|
@@ -53,7 +38,7 @@ dependencies:
|
|
|
53
38
|
- !ruby/object:Gem::Version
|
|
54
39
|
version: '0'
|
|
55
40
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name: rake
|
|
41
|
+
name: rake
|
|
57
42
|
requirement: !ruby/object:Gem::Requirement
|
|
58
43
|
requirements:
|
|
59
44
|
- - ">="
|
|
@@ -67,7 +52,7 @@ dependencies:
|
|
|
67
52
|
- !ruby/object:Gem::Version
|
|
68
53
|
version: '0'
|
|
69
54
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
55
|
+
name: rake-compiler
|
|
71
56
|
requirement: !ruby/object:Gem::Requirement
|
|
72
57
|
requirements:
|
|
73
58
|
- - ">="
|
|
@@ -81,7 +66,7 @@ dependencies:
|
|
|
81
66
|
- !ruby/object:Gem::Version
|
|
82
67
|
version: '0'
|
|
83
68
|
- !ruby/object:Gem::Dependency
|
|
84
|
-
name:
|
|
69
|
+
name: rake-compiler-dock
|
|
85
70
|
requirement: !ruby/object:Gem::Requirement
|
|
86
71
|
requirements:
|
|
87
72
|
- - ">="
|
|
@@ -95,7 +80,7 @@ dependencies:
|
|
|
95
80
|
- !ruby/object:Gem::Version
|
|
96
81
|
version: '0'
|
|
97
82
|
- !ruby/object:Gem::Dependency
|
|
98
|
-
name:
|
|
83
|
+
name: rspec
|
|
99
84
|
requirement: !ruby/object:Gem::Requirement
|
|
100
85
|
requirements:
|
|
101
86
|
- - ">="
|
|
@@ -109,7 +94,7 @@ dependencies:
|
|
|
109
94
|
- !ruby/object:Gem::Version
|
|
110
95
|
version: '0'
|
|
111
96
|
- !ruby/object:Gem::Dependency
|
|
112
|
-
name:
|
|
97
|
+
name: launchy
|
|
113
98
|
requirement: !ruby/object:Gem::Requirement
|
|
114
99
|
requirements:
|
|
115
100
|
- - ">="
|
|
@@ -146,6 +131,7 @@ extra_rdoc_files: []
|
|
|
146
131
|
files:
|
|
147
132
|
- ".github/dependabot.yml"
|
|
148
133
|
- ".github/workflows/ci.yml"
|
|
134
|
+
- ".github/workflows/release.yml"
|
|
149
135
|
- ".github/workflows/windows.yml"
|
|
150
136
|
- ".gitignore"
|
|
151
137
|
- ".rspec"
|
|
@@ -155,14 +141,9 @@ files:
|
|
|
155
141
|
- README.md
|
|
156
142
|
- Rakefile
|
|
157
143
|
- bin/console
|
|
158
|
-
- bin/guard
|
|
159
144
|
- bin/rspec
|
|
160
145
|
- bin/runner
|
|
161
146
|
- bin/setup
|
|
162
|
-
- ci/travis_before_script.sh
|
|
163
|
-
- ci/travis_install.sh
|
|
164
|
-
- ci/travis_retry.sh
|
|
165
|
-
- config/Guardfile
|
|
166
147
|
- docker/Dockerfile
|
|
167
148
|
- docker/Gemfile
|
|
168
149
|
- docker/README.md
|
|
@@ -218,11 +199,10 @@ files:
|
|
|
218
199
|
- pycall.gemspec
|
|
219
200
|
- tasks/docker.rake
|
|
220
201
|
- tasks/pycall.rake
|
|
221
|
-
homepage: https://github.com/
|
|
202
|
+
homepage: https://github.com/red-data-tools/pycall.rb
|
|
222
203
|
licenses:
|
|
223
204
|
- MIT
|
|
224
205
|
metadata: {}
|
|
225
|
-
post_install_message:
|
|
226
206
|
rdoc_options: []
|
|
227
207
|
require_paths:
|
|
228
208
|
- lib
|
|
@@ -237,8 +217,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
237
217
|
- !ruby/object:Gem::Version
|
|
238
218
|
version: '0'
|
|
239
219
|
requirements: []
|
|
240
|
-
rubygems_version:
|
|
241
|
-
signing_key:
|
|
220
|
+
rubygems_version: 4.0.16
|
|
242
221
|
specification_version: 4
|
|
243
222
|
summary: pycall
|
|
244
223
|
test_files: []
|
data/bin/guard
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
#
|
|
4
|
-
# This file was generated by Bundler.
|
|
5
|
-
#
|
|
6
|
-
# The application 'guard' is installed as part of a gem, and
|
|
7
|
-
# this file is here to facilitate running it.
|
|
8
|
-
#
|
|
9
|
-
|
|
10
|
-
require "pathname"
|
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
|
12
|
-
Pathname.new(__FILE__).realpath)
|
|
13
|
-
|
|
14
|
-
require "rubygems"
|
|
15
|
-
require "bundler/setup"
|
|
16
|
-
|
|
17
|
-
load Gem.bin_path("guard", "guard")
|
data/ci/travis_before_script.sh
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
__DIR__=$(cd $(dirname $BASH_SOURCE); pwd)
|
|
2
|
-
. $__DIR__/travis_retry.sh
|
|
3
|
-
|
|
4
|
-
set -ex
|
|
5
|
-
|
|
6
|
-
if test -z "$PYENV_VERSION"; then
|
|
7
|
-
echo "ERROR: PYENV_VERSION is not provided" >2
|
|
8
|
-
exit 1
|
|
9
|
-
fi
|
|
10
|
-
|
|
11
|
-
if test -n "$LIBPYTHON"; then
|
|
12
|
-
export LIBPYTHON=$(pyenv root)/$LIBPYTHON
|
|
13
|
-
fi
|
|
14
|
-
|
|
15
|
-
case "$PYENV_VERSION" in
|
|
16
|
-
*conda*)
|
|
17
|
-
source $(pyenv prefix)/bin/activate test-environment
|
|
18
|
-
;;
|
|
19
|
-
esac
|
|
20
|
-
|
|
21
|
-
set +ex
|
data/ci/travis_install.sh
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
#! /bin/bash
|
|
2
|
-
|
|
3
|
-
__DIR__=$(cd $(dirname $BASH_SOURCE); pwd)
|
|
4
|
-
. $__DIR__/travis_retry.sh
|
|
5
|
-
|
|
6
|
-
set -ex
|
|
7
|
-
|
|
8
|
-
if test -z "$PYENV_VERSION"; then
|
|
9
|
-
echo "ERROR: PYENV_VERSION is not provided" >2
|
|
10
|
-
exit 1
|
|
11
|
-
fi
|
|
12
|
-
|
|
13
|
-
pyenv_root=$(pyenv root)
|
|
14
|
-
|
|
15
|
-
if test -n "$LIBPYTHON"; then
|
|
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
|
|
24
|
-
fi
|
|
25
|
-
|
|
26
|
-
(
|
|
27
|
-
cd $(pyenv root)
|
|
28
|
-
if [ -d .git ]; then
|
|
29
|
-
git fetch origin
|
|
30
|
-
git checkout master
|
|
31
|
-
git reset --hard origin/master
|
|
32
|
-
fi
|
|
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
|
|
42
|
-
|
|
43
|
-
case "$PYENV_VERSION" in
|
|
44
|
-
*conda*)
|
|
45
|
-
case "$PYENV_VERSION" in
|
|
46
|
-
*conda2*)
|
|
47
|
-
python_version=2.7
|
|
48
|
-
;;
|
|
49
|
-
*)
|
|
50
|
-
python_version=3.6
|
|
51
|
-
;;
|
|
52
|
-
esac
|
|
53
|
-
conda config --set always_yes yes --set changeps1 no
|
|
54
|
-
travis_retry conda update -q conda
|
|
55
|
-
conda info -a
|
|
56
|
-
travis_retry conda create -q -n test-environment python=$python_version numpy
|
|
57
|
-
source $(pyenv prefix)/bin/activate test-environment
|
|
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
|
-
;;
|
|
64
|
-
*)
|
|
65
|
-
travis_retry pip install --user numpy
|
|
66
|
-
;;
|
|
67
|
-
esac
|
|
68
|
-
|
|
69
|
-
bundle install
|
data/ci/travis_retry.sh
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
travis_retry ()
|
|
2
|
-
{
|
|
3
|
-
local result=0
|
|
4
|
-
local count=1
|
|
5
|
-
while [ $count -le 3 ]; do
|
|
6
|
-
[ $result -ne 0 ] && {
|
|
7
|
-
echo -e "\n${ANSI_RED}The command \"$@\" failed. Retrying, $count of 3.${ANSI_RESET}\n" 1>&2
|
|
8
|
-
}
|
|
9
|
-
"$@"
|
|
10
|
-
result=$?
|
|
11
|
-
[ $result -eq 0 ] && break
|
|
12
|
-
count=$(($count + 1))
|
|
13
|
-
sleep 1
|
|
14
|
-
done
|
|
15
|
-
[ $count -gt 3 ] && {
|
|
16
|
-
echo -e "\n${ANSI_RED}The command \"$@\" failed 3 times.${ANSI_RESET}\n" 1>&2
|
|
17
|
-
}
|
|
18
|
-
return $result
|
|
19
|
-
}
|
data/config/Guardfile
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# More info at https://github.com/guard/guard#readme
|
|
2
|
-
|
|
3
|
-
if RUBY_PLATFORM =~ /darwin/
|
|
4
|
-
notification :terminal_notifier, app_name: 'pycall.gem ::', activate: 'com.googlecode.iTerm2'
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
directories %w(config lib spec).select { |d|
|
|
8
|
-
Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
watch('config/Guardfile') do
|
|
12
|
-
UI.info "Exiting guard because config changed"
|
|
13
|
-
exit 0
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
guard :rspec, cmd: 'bin/rspec' do
|
|
17
|
-
require "guard/rspec/dsl"
|
|
18
|
-
dsl = Guard::RSpec::Dsl.new(self)
|
|
19
|
-
|
|
20
|
-
# RSpec files
|
|
21
|
-
rspec = dsl.rspec
|
|
22
|
-
watch(rspec.spec_helper) { rspec.spec_dir }
|
|
23
|
-
watch(rspec.spec_support) { rspec.spec_dir }
|
|
24
|
-
watch(rspec.spec_files)
|
|
25
|
-
|
|
26
|
-
# Ruby files
|
|
27
|
-
ruby = dsl.ruby
|
|
28
|
-
dsl.watch_spec_files_for(ruby.lib_files)
|
|
29
|
-
watch('lib/pycall/libpython.rb') { 'spec' }
|
|
30
|
-
end
|