Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

FIX: macos: Add update capability to interval/singleshot timer properties#29018

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes fromall 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
8 changes: 3 additions & 5 deletionslib/matplotlib/backend_bases.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2320,13 +2320,11 @@ def start_event_loop(self, timeout=0):
"""
if timeout <= 0:
timeout = np.inf
timestep = 0.01
counter = 0
t_end = time.perf_counter() + timeout
self._looping = True
while self._looping andcounter * timestep < timeout:
while self._looping andtime.perf_counter() < t_end:
self.flush_events()
time.sleep(timestep)
counter += 1
time.sleep(0.01) # Pause for 10ms

def stop_event_loop(self):
"""
Expand Down
4 changes: 4 additions & 0 deletionslib/matplotlib/backends/backend_wx.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -69,6 +69,10 @@ def _timer_set_interval(self):
if self._timer.IsRunning():
self._timer_start() # Restart with new interval.

def _timer_set_single_shot(self):
if self._timer.IsRunning():
self._timer_start() # Restart with new interval.


@_api.deprecated(
"2.0", name="wx", obj_type="backend", removal="the future",
Expand Down
71 changes: 44 additions & 27 deletionslib/matplotlib/tests/test_backends_interactive.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -621,37 +621,54 @@ def test_blitting_events(env):


def _impl_test_interactive_timers():
# NOTE: We run the timer tests in parallel to avoid longer sequential
# delays which adds to the testing time. Add new tests to one of
# the current event loop iterations if possible.
from unittest.mock import Mock
import matplotlib.pyplot as plt

fig = plt.figure()
event_loop_time = 0.5 # in seconds

# A timer with <1 millisecond gets converted to int and therefore 0
# milliseconds, which the mac framework interprets as singleshot.
# We only want singleshot if we specify that ourselves, otherwise we want
# a repeating timer
import os
from unittest.mock import Mock
import matplotlib.pyplot as plt
# increase pause duration on CI to let things spin up
# particularly relevant for gtk3cairo
pause_time = 2 if os.getenv("CI") else 0.5
fig = plt.figure()
plt.pause(pause_time)
timer = fig.canvas.new_timer(0.1)
mock = Mock()
timer.add_callback(mock)
timer.start()
plt.pause(pause_time)
timer.stop()
assert mock.call_count > 1

# Now turn it into a single shot timer and verify only one gets triggered
mock.call_count = 0
timer.single_shot = True
timer.start()
plt.pause(pause_time)
assert mock.call_count == 1

# Make sure we can start the timer a second time
timer.start()
plt.pause(pause_time)
assert mock.call_count == 2
timer_repeating = fig.canvas.new_timer(0.1)
mock_repeating = Mock()
timer_repeating.add_callback(mock_repeating)
timer_repeating.start()

timer_single_shot = fig.canvas.new_timer(100)
mock_single_shot = Mock()
timer_single_shot.add_callback(mock_single_shot)
# Start as a repeating timer then change to singleshot via the attribute
timer_single_shot.start()
timer_single_shot.single_shot = True

fig.canvas.start_event_loop(event_loop_time)
# NOTE: The timer is as fast as possible, but this is different between backends
# so we can't assert on the exact number but it should be faster than 100ms
expected_100ms_calls = int(event_loop_time / 0.1)
assert mock_repeating.call_count > expected_100ms_calls, \
f"Expected more than {expected_100ms_calls} calls, " \
f"got {mock_repeating.call_count}"
assert mock_single_shot.call_count == 1, \
f"Expected 1 call, got {mock_single_shot.call_count}"

# Test updating the interval updates a running timer
timer_repeating.interval = 100
mock_repeating.call_count = 0
# Make sure we can start the timer after stopping a singleshot timer
timer_single_shot.stop()
timer_single_shot.start()

fig.canvas.start_event_loop(event_loop_time)
assert 1 < mock_repeating.call_count <= expected_100ms_calls + 1, \
f"Expected less than {expected_100ms_calls + 1} calls, " \
"got {mock.call_count}"
assert mock_single_shot.call_count == 2, \
f"Expected 2 calls, got {mock_single_shot.call_count}"
plt.close("all")


Expand Down
18 changes: 18 additions & 0 deletionssrc/_macosx.m
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1789,6 +1789,18 @@ - (void)flagsChanged:(NSEvent *)event
Py_RETURN_NONE;
}

static PyObject*
Timer__timer_update(Timer* self)
{
// stop and invalidate a timer if it is already running and then create a new one
// where the start() method retrieves the updated interval internally
if (self->timer) {
Timer__timer_stop_impl(self);
gil_call_method((PyObject*)self,"_timer_start");
}
Py_RETURN_NONE;
}

staticvoid
Timer_dealloc(Timer* self)
{
Expand All@@ -1815,6 +1827,12 @@ - (void)flagsChanged:(NSEvent *)event
{"_timer_stop",
(PyCFunction)Timer__timer_stop,
METH_NOARGS},
{"_timer_set_interval",
(PyCFunction)Timer__timer_update,
METH_NOARGS},
{"_timer_set_single_shot",
(PyCFunction)Timer__timer_update,
METH_NOARGS},
{}// sentinel
},
};
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp