Skip to content

misc IPython 9 compatibility #931

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion ipyparallel/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
from ipyparallel import error, serialize, util
from ipyparallel.serialize import PrePickled, Reference
from ipyparallel.util import _OutputProducingThread as Thread
from ipyparallel.util import _TermColors

from .asyncresult import AsyncHubResult, AsyncResult
from .futures import MessageFuture, multi_future
Expand Down Expand Up @@ -161,11 +162,30 @@ def _plaintext(self) -> str:
if not text_out:
return ''

ip = get_ipython()
if ip is None:
colors = "NoColor"
else:
colors = ip.colors

if colors.lower() == "nocolor":
out = normal = ""
else:
out = _TermColors.Red
normal = _TermColors.Normal

if '\n' in text_out and not text_out.startswith('\n'):
# add newline for multiline reprs
text_out = '\n' + text_out

return f"Out[{self.metadata['engine_id']}:{self.execution_count}]: {text_out}"
return ''.join(
[
out,
f"Out[{self.metadata['engine_id']}:{self.execution_count}]: ",
normal,
text_out,
]
)

def _repr_pretty_(self, p, cycle):
p.text(self._plaintext())
Expand Down
2 changes: 2 additions & 0 deletions ipyparallel/engine/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,8 @@ def send_with_metadata(
if self.use_mpi and self.init_mpi:
app.exec_lines.insert(0, self.init_mpi)
app.init_profile_dir()
app.init_gui_pylab()
app.init_extensions()
app.init_code()

# redirect output at the end, only after start is called
Expand Down
2 changes: 1 addition & 1 deletion ipyparallel/tests/clienttest.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def generate_output():
a rich displayable object.
"""

from IPython.core.display import HTML, Math, display
from IPython.display import HTML, Math, display

print("stdout")
print("stderr", file=sys.stderr)
Expand Down
28 changes: 16 additions & 12 deletions ipyparallel/tests/test_magics.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,18 +173,18 @@ def test_cellpx_groupby_order(self):
expected.extend(
[
r'\[output:\d+\]',
'IPython.core.display.HTML',
'IPython..+.HTML',
]
* len(v)
)
expected.extend(
[
r'\[output:\d+\]',
'IPython.core.display.Math',
'IPython..+.Math',
]
* len(v)
)
expected.extend([r'Out\[\d+:\d+\]:.*IPython\.core\.display\.Math'] * len(v))
expected.extend([r'Out\[\d+:\d+\]:.*IPython\..+\.Math'] * len(v))

assert len(lines), len(expected) == io.stdout
for line, expect in zip(lines, expected):
Expand Down Expand Up @@ -440,24 +440,28 @@ def test_result(self):
ip.run_line_magic('pxresult', '')
assert str(data[name]) in io.stdout

def test_px_pylab(self):
"""%pylab works on engines"""
def test_px_matplotlib(self):
"""%matplotlib inline works on engines"""
pytest.importorskip('matplotlib')
ip = get_ipython()
v = self.client[-1]
v.block = True
v.activate()

with capture_output() as io:
ip.run_line_magic("px", "%pylab inline")

assert (
"Populating the interactive namespace from numpy and matplotlib"
in io.stdout
)
ip.run_line_magic(
"px",
"\n".join(
[
"%matplotlib inline",
"import numpy as np",
"import matplotlib.pyplot as plt",
]
),
)

with capture_output(display=False) as io:
ip.run_line_magic("px", "plot(rand(100))")
ip.run_line_magic("px", "plt.plot(np.random.rand(100))")
assert 'Out[' in io.stdout
assert 'matplotlib.lines' in io.stdout

Expand Down
4 changes: 2 additions & 2 deletions ipyparallel/tests/test_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ def test_execute_magic(self):
def test_execute_displaypub(self):
"""execute tracks display_pub output"""
view = self.client[:]
view.execute("from IPython.core.display import *")
view.execute("from IPython.display import *")
ar = view.execute("[ display(i) for i in range(5) ]", block=True)

expected = [{'text/plain': str(j)} for j in range(5)]
Expand All @@ -625,7 +625,7 @@ def test_execute_displaypub(self):
def test_apply_displaypub(self):
"""apply tracks display_pub output"""
view = self.client[:]
view.execute("from IPython.core.display import *")
view.execute("from IPython.display import *")

@interactive
def publish():
Expand Down
7 changes: 7 additions & 0 deletions ipyparallel/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -836,3 +836,10 @@ def __init__(self, target, **kwargs):
def _wrapped_target(self, target, *args, **kwargs):
_detach_thread_output(self.ident)
return target(*args, **kwargs)


# minimal subset of TermColors, removed from IPython
# not for public consumption
class _TermColors:
Normal = '\033[0m'
Red = '\033[0;31m'
Loading