Skip to content

Commit 83b7ffc

Browse files
committed
Run pytest in julia process
1 parent db1a018 commit 83b7ffc

4 files changed

Lines changed: 82 additions & 8 deletions

File tree

src/convenience.jl

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,29 @@ function install_dependency(package; force=false, dry_run=false)
145145
end
146146

147147

148-
function test_replhelper()
149-
command = `$(PyCall.pyprogramname) -m pytest`
148+
function test_replhelper(args=``; inprocess=false, kwargs...)
149+
if inprocess
150+
test_replhelper_inprocess(args; kwargs...)
151+
else
152+
test_replhelper_cli(args)
153+
end
154+
end
155+
156+
function test_replhelper_inprocess(args; revise=true)
157+
IPython._start_ipython(:ipython_options) # setup replhelper.core._Main
158+
if revise
159+
pyimport("replhelper")[:revise]()
160+
end
161+
cd(@__DIR__) do
162+
code = pyimport("pytest")[:main](collect(args))
163+
if code != 0
164+
error("$(`pytest $args`) failed with code $code")
165+
end
166+
end
167+
end
168+
169+
function test_replhelper_cli(args)
170+
command = `$(PyCall.pyprogramname) -m pytest $args`
150171
@info command
151172
cd(@__DIR__) do
152173
run(command)

src/replhelper/core.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33

44
from __future__ import print_function
55

6-
import warnings
76
import sys
7+
import types
8+
import warnings
89

910
try:
1011
from importlib import reload
@@ -147,6 +148,25 @@ def wrapped(*args, **kwargs):
147148
return wrapped
148149

149150

151+
def get_api(main):
152+
if main is None:
153+
return None
154+
return main._JuliaNameSpace__julia
155+
156+
157+
def get_main(**kwargs):
158+
"""
159+
Create or get cached `Main`.
160+
161+
Caching is required to avoid re-writing to `_Main` when re-entering
162+
to IPython session (where `user_ns` would be ignored).
163+
"""
164+
global _Main
165+
if _Main is None:
166+
_Main = JuliaNameSpace(JuliaAPI(**kwargs))
167+
return _Main
168+
169+
150170
def ipython_options(**kwargs):
151171
global _Main
152172
from traitlets.config import Config
@@ -198,12 +218,27 @@ def customized_ipython(**kwargs):
198218

199219
def revise():
200220
"""Ad-hoc hot reload."""
221+
222+
Main = _Main
223+
201224
import replhelper
202225
reload(replhelper.core)
203226

204-
if _Main is not None:
205-
_Main.__class__ = replhelper.core.JuliaNameSpace
206-
_Main._JuliaNameSpace__julia.__class__ = replhelper.core.JuliaAPI
207-
replhelper.core._Main = _Main
227+
if Main is not None:
228+
Main.__class__ = replhelper.core.JuliaNameSpace
229+
Main._JuliaNameSpace__julia.__class__ = replhelper.core.JuliaAPI
230+
replhelper.core._Main = Main
231+
232+
try:
233+
replhelper.tests
234+
except AttributeError:
235+
return
236+
237+
# *Try* reloading modules `replhelper.tests.*`. If there are
238+
# dependencies between those modules, it's not going to work.
239+
for (name, module) in sorted(vars(replhelper.tests).items(),
240+
key=lambda pair: pair[0]):
241+
if isinstance(module, types.ModuleType):
242+
reload(module)
208243

209244
reload(replhelper)

src/replhelper/tests/conftest.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import pytest
2+
3+
from .. import core
4+
5+
6+
@pytest.fixture
7+
def Main():
8+
""" pytest fixture for providing a Julia `Main` name space. """
9+
if core._Main is None:
10+
pytest.skip("Main not configured (not called from IPython.jl?)")
11+
else:
12+
return core._Main
13+
14+
15+
@pytest.fixture
16+
def julia(Main):
17+
""" pytest fixture for providing a `JuliaAPI` instance. """
18+
return core.get_api(Main)

test/runtests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ end
1515
include("test_julia_repl.jl")
1616
include("test_convenience.jl")
1717

18-
IPython.test_replhelper()
18+
IPython.test_replhelper(inprocess=true)
1919

2020
# end # module

0 commit comments

Comments
 (0)