self=<tests.ext.test_application.TestApplicationobjectat0x7f1205dc5450>one_time_bot=PytestExtBot[token=640208943:AAFhBjQp9qm3RTxSzUpYzBQjCle-Jjz5hck]monkeypatch=<_pytest.monkeypatch.MonkeyPatchobjectat0x7f1201ed4e20>method='polling'@pytest.mark.parametrize("method", ["polling","webhook"])deftest_stop_running(self,one_time_bot,monkeypatch,method):# asyncio.Event() seems to be hard to use across different threads (awaiting in main# thread, setting in another thread), so we use threading.Event() instead.# This requires the use of run_in_executor, but that's fine.put_update_event=threading.Event()callback_done_event=threading.Event()called_stop_running=threading.Event()assertions= {}asyncdefpost_init(app):# Simply calling app.update_queue.put_nowait(method) in the thread_target doesn't work# for some reason (probably threading magic), so we use an event from the thread_target# to put the update into the queue in the main thread.asyncdeftask(app):awaitasyncio.get_running_loop().run_in_executor(None,put_update_event.wait)awaitapp.update_queue.put(method)app.create_task(task(app))app= (ApplicationBuilder() .application_class(PytestApplication) .updater(PytestUpdater(one_time_bot,asyncio.Queue())) .post_init(post_init) .build() )monkeypatch.setattr(app.bot,"get_updates",empty_get_updates)events= []monkeypatch.setattr(app.updater,"stop",call_after(app.updater.stop,lambda_:events.append("updater.stop")), )monkeypatch.setattr(app,"stop",call_after(app.stop,lambda_:events.append("app.stop")), )monkeypatch.setattr(app,"shutdown",call_after(app.shutdown,lambda_:events.append("app.shutdown")), )monkeypatch.setattr(app.bot,"set_webhook",return_true)monkeypatch.setattr(app.bot,"delete_webhook",return_true)defthread_target():waited=0whilenotapp.running:time.sleep(0.05)waited+=0.05ifwaited>5:pytest.fail("App apparently won't start")time.sleep(0.1)assertions["called_stop_running_not_set"]=notcalled_stop_running.is_set()put_update_event.set()time.sleep(0.1)assertions["called_stop_running_set"]=called_stop_running.is_set()# App should have entered `stop` now but not finished it yet because the callback# is still runningassertions["updater.stop_event"]=events== ["updater.stop"]assertions["app.running_False"]=notapp.runningcallback_done_event.set()time.sleep(0.1)# Now that the update is fully handled, we expect the full shutdownassertions["events"]=events== ["updater.stop","app.stop","app.shutdown"]asyncdefcallback(update,context):context.application.stop_running()called_stop_running.set()awaitasyncio.get_running_loop().run_in_executor(None,callback_done_event.wait)app.add_handler(TypeHandler(object,callback))thread=Thread(target=thread_target)thread.start()ifmethod=="polling":app.run_polling(close_loop=False,drop_pending_updates=True)else:ip="127.0.0.1"port=randrange(1024,49152)app.run_webhook(ip_address=ip,port=port,url_path="TOKEN",drop_pending_updates=False,close_loop=False, )thread.join()assertlen(assertions)==5forkey,valueinassertions.items():>assertvalue,f"assertion '{key}' failed!"EAssertionError:assertion'called_stop_running_set'failed!EassertFalsetests/ext/test_application.py:2547:AssertionError
closes#4593