Skip to content
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

Mock tornado for jupyterlite #381

Merged
merged 1 commit into from
Oct 19, 2021

Conversation

martinRenou
Copy link
Member

See #334

@github-actions
Copy link
Contributor

Binder 👈 Launch a binder notebook on branch martinRenou/ipympl/support_jupyterlite

@lgtm-com
Copy link

lgtm-com bot commented Oct 19, 2021

This pull request introduces 1 alert when merging e5b2cf9 into 76111ce - view on LGTM.com

new alerts:

  • 1 for Unused import

@lgtm-com
Copy link

lgtm-com bot commented Oct 19, 2021

This pull request introduces 1 alert when merging 011ee0f into 558cc47 - view on LGTM.com

new alerts:

  • 1 for Unused import

@martinRenou martinRenou merged commit fb80bd5 into matplotlib:master Oct 19, 2021
@martinRenou martinRenou deleted the support_jupyterlite branch October 19, 2021 11:21
Comment on lines +11 to +14
try:
import micropip # noqa
except ImportError:
sys.modules['tornado'] = types.ModuleType('tornadofake')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@martinRenou I think that the mocking got put into the wrong place here? the idea is that micropip is only available in jupyterlite correct? so it should be:

try:
    import micropip  # noqa
    sys.modules['tornado'] = types.ModuleType('tornadofake')
except ImportError:
   pass

?

@ianhi
Copy link
Collaborator

ianhi commented Oct 24, 2021

This broke the save_animation functionality of mpl-interactions as that does some tricky things with animations. As in the review comment I think that the check for if we're in a pyodide context is not set up correctly.

%matplotlib ipympl
import matplotlib.pyplot as plt
import numpy as np

import mpl_interactions.ipyplot as iplt

x = np.linspace(0, 2 * np.pi, 200)


def f(x, amp, freq):
    return amp * np.sin(x * freq)


# Create the plot as normal
fig, ax = plt.subplots()
controls = iplt.plot(x, f, freq=(0.05, 10, 250), amp=(1, 10))
_ = iplt.title("the Frequency is: {freq:.2f}", controls=controls["freq"])

# save as a gif
anim = controls.save_animation("freq-plot-1.gif", fig, "freq", interval=35)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-2-6978a96bf4a5> in <module>
     18 
     19 # save as a gif
---> 20 anim = controls.save_animation("freq-plot-1.gif", fig, "freq", interval=35)

~/mambaforge/envs/micro/lib/python3.8/site-packages/mpl_interactions/controller.py in save_animation(self, filename, fig, param, interval, func_anim_kwargs, N_frames, **kwargs)
    318         # draw then stop necessary to prevent an extra loop after finished saving
    319         # see https://discourse.matplotlib.org/t/how-to-prevent-funcanimation-looping-a-single-time-after-save/21680/2
--> 320         fig.canvas.draw()
    321         anim.event_source.stop()
    322         anim.save(filename, **kwargs)

~/mambaforge/envs/micro/lib/python3.8/site-packages/matplotlib/backends/backend_webagg_core.py in draw(self)
    151         self._png_is_old = True
    152         try:
--> 153             super().draw()
    154         finally:
    155             self.manager.refresh_all()  # Swap the frames.

~/mambaforge/envs/micro/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py in draw(self)
    404              (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
    405               else nullcontext()):
--> 406             self.figure.draw(self.renderer)
    407             # A GUI class may be need to update a window using this draw, so
    408             # don't forget to call the superclass.

~/mambaforge/envs/micro/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     72     @wraps(draw)
     73     def draw_wrapper(artist, renderer, *args, **kwargs):
---> 74         result = draw(artist, renderer, *args, **kwargs)
     75         if renderer._rasterizing:
     76             renderer.stop_rasterizing()

~/mambaforge/envs/micro/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     49                 renderer.start_filter()
     50 
---> 51             return draw(artist, renderer, *args, **kwargs)
     52         finally:
     53             if artist.get_agg_filter() is not None:

~/mambaforge/envs/micro/lib/python3.8/site-packages/matplotlib/figure.py in draw(self, renderer)
   2788             self.stale = False
   2789 
-> 2790         self.canvas.draw_event(renderer)
   2791 
   2792     def draw_artist(self, a):

~/mambaforge/envs/micro/lib/python3.8/site-packages/matplotlib/backend_bases.py in draw_event(self, renderer)
   1790         s = 'draw_event'
   1791         event = DrawEvent(s, self, renderer)
-> 1792         self.callbacks.process(s, event)
   1793 
   1794     def resize_event(self):

~/mambaforge/envs/micro/lib/python3.8/site-packages/matplotlib/cbook/__init__.py in process(self, s, *args, **kwargs)
    273                 except Exception as exc:
    274                     if self.exception_handler is not None:
--> 275                         self.exception_handler(exc)
    276                     else:
    277                         raise

~/mambaforge/envs/micro/lib/python3.8/site-packages/matplotlib/cbook/__init__.py in _exception_printer(exc)
     87 def _exception_printer(exc):
     88     if _get_running_interactive_framework() in ["headless", None]:
---> 89         raise exc
     90     else:
     91         traceback.print_exc()

~/mambaforge/envs/micro/lib/python3.8/site-packages/matplotlib/cbook/__init__.py in process(self, s, *args, **kwargs)
    268             if func is not None:
    269                 try:
--> 270                     func(*args, **kwargs)
    271                 # this does not capture KeyboardInterrupt, SystemExit,
    272                 # and GeneratorExit

~/mambaforge/envs/micro/lib/python3.8/site-packages/matplotlib/animation.py in _start(self, *args)
    994         # actually start the event_source.
    995         self.event_source.add_callback(self._step)
--> 996         self.event_source.start()
    997 
    998     def _stop(self, *args):

~/mambaforge/envs/micro/lib/python3.8/site-packages/matplotlib/backend_bases.py in start(self, interval)
   1132         if interval is not None:
   1133             self.interval = interval
-> 1134         self._timer_start()
   1135 
   1136     def stop(self):

~/mambaforge/envs/micro/lib/python3.8/site-packages/matplotlib/backends/backend_webagg_core.py in _timer_start(self)
     93                 self._on_timer)
     94         else:
---> 95             self._timer = tornado.ioloop.PeriodicCallback(
     96                 self._on_timer,
     97                 max(self.interval, 1e-6))

AttributeError: module 'tornadofake' has no attribute 'ioloop'

@ianhi
Copy link
Collaborator

ianhi commented Oct 24, 2021

simpler matplotlib only reproduction:

%matplotlib ipympl

from matplotlib import pyplot as plt
from matplotlib import animation

fig = plt.figure()

def animate(i):
    pass

anim = animation.FuncAnimation(fig, animate)
fig.canvas.draw()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants