Skip to content

Commit 1bff201

Browse files
authored
Merge 0d1f074 into 5d40ad4
2 parents 5d40ad4 + 0d1f074 commit 1bff201

1 file changed

Lines changed: 23 additions & 17 deletions

File tree

source/core.py

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99

1010
from dataclasses import dataclass
11-
from typing import List, Optional
11+
from typing import Callable, Dict, List, Optional, Union
1212
import comtypes
1313
import sys
1414
import winVersion
@@ -24,6 +24,7 @@
2424
import addonHandler
2525
import extensionPoints
2626
import garbageHandler
27+
import wx
2728

2829

2930
# inform those who want to know that NVDA has finished starting up.
@@ -72,7 +73,6 @@ def handleReplaceCLIArg(cliArgument: str) -> bool:
7273
if not isParamKnown:
7374
unknownCLIParams.append(param)
7475
if unknownCLIParams:
75-
import wx
7676
gui.messageBox(
7777
# Translators: Shown when NVDA has been started with unknown command line parameters.
7878
_("The following command line parameters are unknown to NVDA: {params}").format(
@@ -84,7 +84,6 @@ def handleReplaceCLIArg(cliArgument: str) -> bool:
8484
wx.OK | wx.ICON_ERROR
8585
)
8686
if config.conf.baseConfigError:
87-
import wx
8887
gui.messageBox(
8988
# Translators: A message informing the user that there are errors in the configuration file.
9089
_("Your configuration file contains errors. "
@@ -102,7 +101,6 @@ def handleReplaceCLIArg(cliArgument: str) -> bool:
102101
gui.mainFrame.onToggleSpeechViewerCommand(evt=None)
103102
import inputCore
104103
if inputCore.manager.userGestureMap.lastUpdateContainedError:
105-
import wx
106104
gui.messageBox(_("Your gesture map file contains errors.\n"
107105
"More details about the errors can be found in the log file."),
108106
_("gesture map File Error"), wx.OK|wx.ICON_EXCLAMATION)
@@ -114,7 +112,6 @@ def handleReplaceCLIArg(cliArgument: str) -> bool:
114112
if updateCheck and not config.conf['update']['askedAllowUsageStats']:
115113
# a callback to save config after the usage stats question dialog has been answered.
116114
def onResult(ID):
117-
import wx
118115
if ID in (wx.ID_YES,wx.ID_NO):
119116
try:
120117
config.conf.save()
@@ -267,8 +264,7 @@ def _setInitialFocus():
267264
log.exception("Error retrieving initial focus")
268265

269266

270-
def getWxLangOrNone() -> Optional['wx.LanguageInfo']:
271-
import wx
267+
def getWxLangOrNone() -> Optional[wx.LanguageInfo]:
272268
lang = languageHandler.getLanguage()
273269
wxLocaleObj = wx.Locale()
274270
wxLang = wxLocaleObj.FindLanguageInfo(lang)
@@ -346,8 +342,6 @@ def _closeAllWindows():
346342
"""
347343
import gui
348344
from gui.settingsDialogs import SettingsDialog
349-
from typing import Dict
350-
import wx
351345

352346
app = wx.GetApp()
353347

@@ -483,7 +477,6 @@ def main():
483477
log.debugWarning("Slow starting core (%.2f sec)" % (time.time()-globalVars.startTime))
484478
# Translators: This is spoken when NVDA is starting.
485479
speech.speakMessage(_("Loading NVDA. Please wait..."))
486-
import wx
487480
import six
488481
log.info("Using wx version %s with six version %s"%(wx.version(), six.__version__))
489482
class App(wx.App):
@@ -863,21 +856,34 @@ def requestPump():
863856
return
864857
# This isn't the main thread. wx timers cannot be run outside the main thread.
865858
# Therefore, Have wx start it in the main thread with a CallAfter.
866-
import wx
867859
wx.CallAfter(_pump.Start,PUMP_MAX_DELAY, True)
868860

869-
def callLater(delay, callable, *args, **kwargs):
861+
862+
class NVDANotInitializedError(Exception):
863+
pass
864+
865+
866+
def callLater(
867+
delay: float,
868+
callable: Callable,
869+
*args,
870+
**kwargs
871+
) -> Union[wx.CallLater, None]:
870872
"""Call a callable once after the specified number of milliseconds.
871873
As the call is executed within NVDA's core queue, it is possible that execution will take place slightly after the requested time.
872874
This function should never be used to execute code that brings up a modal UI as it will cause NVDA's core to block.
873-
This function can be safely called from any thread.
875+
This function can be safely called from any thread once NVDA has been initialized.
874876
"""
875-
import wx
877+
if wx.GetApp() is None:
878+
# If NVDA has not fully initialized yet, the wxApp may not be initialized.
879+
# wx.CallLater and wx.CallAfter requires the wxApp to be initialized.
880+
raise NVDANotInitializedError("Cannot schedule callable, wx.App is not initialized")
876881
if threading.get_ident() == mainThreadId:
877882
return wx.CallLater(delay, _callLaterExec, callable, args, kwargs)
878883
else:
879-
return wx.CallAfter(wx.CallLater,delay, _callLaterExec, callable, args, kwargs)
884+
return wx.CallAfter(wx.CallLater, delay, _callLaterExec, callable, args, kwargs)
885+
880886

881-
def _callLaterExec(callable, args, kwargs):
887+
def _callLaterExec(callable: Callable, args, kwargs):
882888
import queueHandler
883-
queueHandler.queueFunction(queueHandler.eventQueue,callable,*args, **kwargs)
889+
queueHandler.queueFunction(queueHandler.eventQueue, callable, *args, **kwargs)

0 commit comments

Comments
 (0)