Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
3 changes: 2 additions & 1 deletion lib/matplotlib/backends/backend_nbagg.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
from matplotlib.backend_bases import _Backend, NavigationToolbar2
from matplotlib.backends.backend_webagg_core import (
FigureCanvasWebAggCore, FigureManagerWebAgg, NavigationToolbar2WebAgg,
TimerTornado)
TimerTornado, TimerAsyncio
)


def connection_info():
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/backends/backend_webagg.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from matplotlib.backend_bases import _Backend
from matplotlib._pylab_helpers import Gcf
from . import backend_webagg_core as core
from .backend_webagg_core import TimerTornado
Comment thread
martinRenou marked this conversation as resolved.
from .backend_webagg_core import TimerAsyncio, TimerTornado


class ServerThread(threading.Thread):
Expand Down
45 changes: 42 additions & 3 deletions lib/matplotlib/backends/backend_webagg_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
# way over a web socket.
#
# - `backend_webagg.py` contains a concrete implementation of a basic
# application, implemented with tornado.
# application, implemented with asyncio.

import asyncio
import datetime
from io import BytesIO, StringIO
import json
Expand All @@ -19,7 +20,6 @@

import numpy as np
from PIL import Image
import tornado

from matplotlib import _api, backend_bases, backend_tools
from matplotlib.backends import backend_agg
Expand Down Expand Up @@ -85,6 +85,8 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

def _timer_start(self):
import tornado

self._timer_stop()
if self._single:
ioloop = tornado.ioloop.IOLoop.instance()
Expand All @@ -98,6 +100,8 @@ def _timer_start(self):
self._timer.start()

def _timer_stop(self):
import tornado

if self._timer is None:
return
elif self._single:
Expand All @@ -114,8 +118,43 @@ def _timer_set_interval(self):
self._timer_start()


class TimerAsyncio(backend_bases.TimerBase):
def __init__(self, *args, **kwargs):
self._task = None
super().__init__(*args, **kwargs)

async def _timer_task(self, interval):
while True:
try:
await asyncio.sleep(interval)
self._on_timer()

if self._single:
break
except asyncio.CancelledError:
break

def _timer_start(self):
self._timer_stop()

self._task = asyncio.ensure_future(
Comment thread
martinRenou marked this conversation as resolved.
self._timer_task(max(self.interval / 1_000., 1e-6))
)
Comment thread
QuLogic marked this conversation as resolved.

def _timer_stop(self):
if self._task is not None:
self._task.cancel()
self._task = None

def _timer_set_interval(self):
# Only stop and restart it if the timer has already been started
if self._task is not None:
self._timer_stop()
self._timer_start()


class FigureCanvasWebAggCore(backend_agg.FigureCanvasAgg):
_timer_cls = TimerTornado
_timer_cls = TimerAsyncio
# Webagg and friends having the right methods, but still
# having bugs in practice. Do not advertise that it works until
# we can debug this.
Expand Down