Skip to content

Commit 97f6c22

Browse files
author
Christopher Doris
committed
Merge remote-tracking branch 'origin' into api
2 parents 219f9a2 + b9fee86 commit 97f6c22

37 files changed

+563
-267
lines changed

.github/workflows/benchmark_pr.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: Benchmark PR
2+
on:
3+
pull_request:
4+
5+
jobs:
6+
bench:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: MilesCranmer/AirspeedVelocity.jl@action-v1
10+
with:
11+
julia-version: "1"
12+
tune: "true"
13+
# Post to "summary" tab of workflow run:
14+
job-summary: "true"
15+
# Run benchmark using PR's version of the script:
16+
bench-on: ${{ github.event.pull_request.head.sha }}

.github/workflows/tests-nightly.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ on:
1010

1111
jobs:
1212
tests:
13-
name: Test (${{ matrix.os }}-${{ matrix.arch }}, julia ${{ matrix.jlversion }})
13+
name: Test Julia (${{ matrix.jlversion }}, ${{ matrix.os }}-${{ matrix.arch }})
1414
runs-on: ${{ matrix.os }}
1515
strategy:
1616
fail-fast: false

.github/workflows/tests.yml

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,70 +12,89 @@ on:
1212

1313
jobs:
1414
julia:
15-
name: Test (${{ matrix.os }}, julia ${{ matrix.jlversion }})
15+
name: Test Julia (${{ matrix.jlversion }}, ${{ matrix.os }})
1616
runs-on: ${{ matrix.os }}
1717
strategy:
18-
fail-fast: true
18+
fail-fast: false
1919
matrix:
2020
arch: [x64] # x86 unsupported by MicroMamba
2121
os: [ubuntu-latest, windows-latest, macos-latest]
2222
jlversion: ['1','1.9']
23+
2324
steps:
2425
- uses: actions/checkout@v4
26+
2527
- name: Set up Julia ${{ matrix.jlversion }}
2628
uses: julia-actions/setup-julia@v2
2729
with:
2830
version: ${{ matrix.jlversion }}
2931
arch: ${{ matrix.arch }}
32+
3033
- uses: julia-actions/cache@v2
34+
3135
- name: Build package
3236
uses: julia-actions/julia-buildpkg@v1
37+
3338
- name: Run tests
3439
uses: julia-actions/julia-runtest@v1
3540
env:
3641
JULIA_DEBUG: PythonCall
3742
JULIA_NUM_THREADS: '2'
43+
3844
- name: Process coverage
3945
uses: julia-actions/julia-processcoverage@v1
46+
4047
- name: Upload coverage to Codecov
4148
uses: codecov/codecov-action@v5
4249
env:
4350
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
51+
4452
python:
45-
name: Test (${{ matrix.os }}, python ${{ matrix.pyversion }})
53+
name: Test Python (${{ matrix.pyversion }}, ${{ matrix.os }})
4654
runs-on: ${{ matrix.os }}
4755
strategy:
48-
fail-fast: true
56+
fail-fast: false
4957
matrix:
5058
os: [ubuntu-latest, windows-latest, macos-latest]
51-
pyversion: ["3.x", "3.8"]
59+
pyversion: ["3", "3.9"]
60+
5261
steps:
5362
- uses: actions/checkout@v4
63+
5464
- name: Set up Python ${{ matrix.pyversion }}
5565
uses: actions/setup-python@v5
5666
with:
5767
python-version: ${{ matrix.pyversion }}
68+
69+
- name: Set up uv
70+
uses: astral-sh/setup-uv@v6
71+
with:
72+
python-version: ${{ matrix.pyversion }}
73+
5874
- name: Set up Julia
5975
uses: julia-actions/setup-julia@v2
6076
with:
6177
version: '1'
78+
6279
- name: Install dependencies
6380
run: |
64-
python -m pip install --upgrade pip
65-
pip install flake8 pytest pytest-cov nbval numpy
6681
cp pysrc/juliacall/juliapkg-dev.json pysrc/juliacall/juliapkg.json
67-
pip install -e .
82+
uv sync --dev
83+
6884
- name: Lint with flake8
6985
run: |
7086
# stop the build if there are Python syntax errors or undefined names
71-
flake8 . --count --select=E9,F63,F7,F82 --ignore=F821 --show-source --statistics
87+
uv run flake8 ./pysrc ./pytest --count --select=E9,F63,F7,F82 --ignore=F821 --show-source --statistics
7288
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
73-
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
89+
uv run flake8 ./pysrc ./pytest --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
90+
7491
- name: Run tests
7592
run: |
76-
pytest -s --nbval --cov=pysrc ./pytest/
93+
uv run pytest -s --nbval --cov=pysrc ./pytest/
7794
env:
7895
PYTHON_JULIACALL_THREADS: '2'
96+
PYTHON_JULIACALL_HANDLE_SIGNALS: 'yes'
97+
7998
- name: Upload coverage to Codecov
8099
uses: codecov/codecov-action@v5
81100
env:

CondaPkg.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ version = "<=julia"
66

77
[deps.python]
88
build = "**cpython**"
9-
version = ">=3.8,<4"
9+
version = ">=3.9,<4"

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "PythonCall"
22
uuid = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
33
authors = ["Christopher Doris <github.com/cjdoris>"]
4-
version = "0.9.25"
4+
version = "0.9.26"
55

66
[deps]
77
CondaPkg = "992eb4ea-22a4-4c89-a5bb-47a3300528ab"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Bringing [**Python®**](https://www.python.org/) and [**Julia**](https://juliala
1414
- Fast non-copying conversion of numeric arrays in either direction: modify Python arrays (e.g. `bytes`, `array.array`, `numpy.ndarray`) from Julia or Julia arrays from Python.
1515
- Helpful wrappers: interpret Python sequences, dictionaries, arrays, dataframes and IO streams as their Julia counterparts, and vice versa.
1616
- Beautiful stack-traces.
17-
- Supports modern systems: tested on Windows, MacOS and Linux, 64-bit, Julia 1.9 upwards and Python 3.8 upwards.
17+
- Supports modern systems: tested on Windows, MacOS and Linux, 64-bit, Julia 1.9 upwards and Python 3.9 upwards.
1818

1919
⭐ If you like this, a GitHub star would be lovely thank you. ⭐
2020

benchmark/Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[deps]
2+
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"

benchmark/benchmarks.jl

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using BenchmarkTools
2+
using PythonCall
3+
using PythonCall: pydel!, pyimport, pydict, pystr, pyrange
4+
5+
const SUITE = BenchmarkGroup()
6+
7+
function test_pydict_init()
8+
random = pyimport("random").random
9+
x = pydict()
10+
for i in pyrange(1000)
11+
x[pystr(i)] = i + random()
12+
end
13+
return x
14+
end
15+
16+
SUITE["basic"]["julia"]["pydict"]["init"] = @benchmarkable test_pydict_init()
17+
18+
function test_pydict_pydel()
19+
random = pyimport("random").random
20+
x = pydict()
21+
for i in pyrange(1000)
22+
k = pystr(i)
23+
r = random()
24+
v = i + r
25+
x[k] = v
26+
pydel!(k)
27+
pydel!(r)
28+
pydel!(v)
29+
pydel!(i)
30+
end
31+
return x
32+
end
33+
34+
SUITE["basic"]["julia"]["pydict"]["pydel"] = @benchmarkable test_pydict_pydel()
35+
36+
@generated function test_atpy(::Val{use_pydel}) where {use_pydel}
37+
quote
38+
@py begin
39+
import random: random
40+
x = {}
41+
for i in range(1000)
42+
x[str(i)] = i + random()
43+
$(use_pydel ? :(@jl PythonCall.pydel!(i)) : :(nothing))
44+
end
45+
x
46+
end
47+
end
48+
end
49+
50+
SUITE["basic"]["@py"]["pydict"]["init"] = @benchmarkable test_atpy(Val(false))
51+
SUITE["basic"]["@py"]["pydict"]["pydel"] = @benchmarkable test_atpy(Val(true))
52+
53+
54+
include("gcbench.jl")
55+
using .GCBench: append_lots
56+
57+
SUITE["gc"]["full"] = @benchmarkable(
58+
GC.gc(true),
59+
setup=(GC.gc(true); append_lots(size=159)),
60+
seconds=30,
61+
evals=1,
62+
)

benchmark/gcbench.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module GCBench
2+
3+
using PythonCall
4+
5+
function append_lots(; iters=100 * 1024, size=1596)
6+
v = pylist()
7+
for i = 1:iters
8+
v.append(pylist(rand(size)))
9+
end
10+
return v
11+
end
12+
13+
end

docs/src/faq.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,19 @@ To force PythonCall to use the same Python interpreter as PyCall, set the enviro
1010

1111
Alternatively, to force PyCall to use the same interpreter as PythonCall, set the environment variable `PYTHON` to [`PythonCall.python_executable_path()`](@ref) and then `Pkg.build("PyCall")`. You will need to do this each time you change project, because PythonCall by default uses a different Python for each project.
1212

13-
## Is PythonCall/JuliaCall thread safe?
13+
## [Is PythonCall/JuliaCall thread safe?](@id faq-multi-threading)
1414

1515
Yes, as of v0.9.22, provided you handle the GIL correctly. See the guides for
1616
[PythonCall](@ref jl-multi-threading) and [JuliaCall](@ref py-multi-threading).
1717

1818
Before, tricks such as disabling the garbage collector were required. See the
1919
[old docs](https://juliapy.github.io/PythonCall.jl/v0.9.21/faq/#Is-PythonCall/JuliaCall-thread-safe?).
2020

21+
When starting a Julia REPL with multiple threads, there must be exactly one interactive thread,
22+
to avoid triggering a segmentation fault on tab completion (issue [#586](https://github.com/JuliaPy/PythonCall.jl/issues/586)).
23+
Check this with `Threads.nthreads(:interactive)` or `versioninfo()`, set it with `JULIA_NUM_THREADS=X,1`,
24+
where `X` is the number of default threads, or use the Julia `--threads` CLI flag, see `julia --help`.
25+
2126
Related issues:
2227
[#201](https://github.com/JuliaPy/PythonCall.jl/issues/201),
2328
[#202](https://github.com/JuliaPy/PythonCall.jl/issues/202),
@@ -89,3 +94,17 @@ Related issues: [#255](https://github.com/JuliaPy/PythonCall.jl/issues/255)
8994
Yes, it may be possible. A good example of that is having Julia running inside the Python that is running inside Blender, as presented in [this Discourse post](https://discourse.julialang.org/t/running-julia-inside-blender-through-vscode-using-pythoncall-juliacall/96838/6).
9095
From the point that one has JuliaCall running inside Python, if it has access to the terminal, one can even launch a Julia REPL there, and if needed connect with VSCode Julia extension to it.
9196
The full Python script to install, launch JuliaCall, and launch a Julia REPL in Blender is [here](https://gist.github.com/cdsousa/d820d27174238c0d48e5252355584172).
97+
98+
## Using PythonCall.jl and CondaPkg.jl in a script
99+
100+
If running from a script, make sure that [CondaPkg.jl](https://github.com/JuliaPy/CondaPkg.jl) is used before [PythonCall.jl](https://github.com/JuliaPy/PythonCall.jl) to ensure proper loading of Python packages in your path. E.g.,
101+
102+
```julia
103+
using CondaPkg
104+
105+
CondaPkg.add("numpy")
106+
107+
using PythonCall
108+
109+
np = pyimport("numpy")
110+
```

0 commit comments

Comments
 (0)