def error_handler(cls, err, tb, action=""): title = "Application aborted" if action: title += f" while {action}" msg = f"{cls.__name__}: {err}" # Try writing traceback to stderr try: tb_info = "".join(traceback.format_list(traceback.extract_tb(tb))) write(f"{title}\n{msg}\n{tb_info}") except Exception: pass # Use dialite to show error in modal window if not TESTING: dialite.fail(title, msg)
def test_unsupported_platform1(): """ Unsupported platform, fallback to terminal. """ o_platform = sys.platform o_stdin = sys.stdin o_app = dialite._the_app sys.platform = 'meh' sys.stdin = FakeStdin() try: app = dialite._get_app(True) assert app.works() assert isinstance(app, TerminalApp) assert dialite.is_supported() with capture_log('info') as log: dialite.inform() assert len(log) == 1 and 'Info: ' in log[0] with capture_log('info') as log: dialite.warn() # no problem assert len(log) == 1 and 'Warning: ' in log[0] with capture_log('info') as log: dialite.fail() assert len(log) == 1 and 'Error: ' in log[0] assert dialite.ask_ok() assert dialite.ask_retry() assert dialite.ask_yesno() sys.stdin.answer = 'no' assert not dialite.ask_ok() assert not dialite.ask_retry() assert not dialite.ask_yesno() finally: sys.platform = o_platform sys.stdin = o_stdin dialite._the_app = o_app
def test_unsupported_platform2(): """ Unsupported platform, and also no terminal. """ o_platform = sys.platform o_stdin = sys.stdin o_app = dialite._the_app o_open = webbrowser.open sys.platform = 'meh' sys.stdin = None webbrowser.open = lambda x: None try: app = dialite._get_app(True) assert app.works() assert isinstance(app, StubApp) assert not dialite.is_supported() dialite.inform() # no problem dialite.warn() # no problem dialite.fail() # no problem # with raises(SystemExit): # dialite.fail() with raises(SystemExit): dialite.ask_ok() with raises(SystemExit): dialite.ask_retry() with raises(SystemExit): dialite.ask_yesno() finally: sys.platform = o_platform sys.stdin = o_stdin dialite._the_app = o_app webbrowser.open = o_open
def test_osx(): """ Pretend that this is OS X. """ o_platform = sys.platform o_app = dialite._the_app sys.platform = 'darwin' try: app = FakeOSXApp() # assert app.works() assert isinstance(app, OSXApp) dialite._the_app = app assert dialite.is_supported() dialite.inform() assert len(app._messages) == 1 dialite.warn() assert len(app._messages) == 2 dialite.fail() assert len(app._messages) == 3 assert dialite.ask_ok() assert len(app._messages) == 4 assert dialite.ask_retry() assert len(app._messages) == 5 assert dialite.ask_yesno() assert len(app._messages) == 6 finally: sys.platform = o_platform dialite._the_app = o_app
def test_linux(): """ Pretend that this is Linux. """ o_platform = sys.platform o_app = dialite._the_app sys.platform = 'linux' try: app = FakeLinuxApp() # assert app.works() assert isinstance(app, LinuxApp) dialite._the_app = app assert dialite.is_supported() dialite.inform() assert len(app._messages) == 1 and 'info' in app._messages[-1] dialite.warn() assert len(app._messages) == 2 and 'warn' in app._messages[-1] dialite.fail() assert len(app._messages) == 3 and 'error' in app._messages[-1] assert dialite.ask_ok() assert len(app._messages) == 4 and 'question' in app._messages[-1] assert dialite.ask_retry() assert len(app._messages) == 5 and 'question' in app._messages[-1] assert dialite.ask_yesno() assert len(app._messages) == 6 and 'question' in app._messages[-1] finally: sys.platform = o_platform dialite._the_app = o_app
assert res is True # Three message boxes res = dialite.inform( PREFIX + "info", "Awesome! " "We will now show three dialogs: info, warn, error. " "This is the first one; an info dialog.", ) assert res is None res = dialite.warn(PREFIX + "warn", "This is the second one; a warning.") assert res is None res = dialite.fail(PREFIX + "error", "This is the third one; an error.") assert res is None # Check results res = dialite.ask_yesno( PREFIX + "check", "Did the past three boxes look something like an info, " "warning, and error dialog, and have only an OK option?", ) assert res is True # Check confirm res = dialite.ask_ok( PREFIX + "confirm",
def launch(url, runtime=None, **kwargs): """ Launch a web runtime in a new process. Parameters: url (str): The url to open, e.g. ``'http://python.org'``. To open a local file use ``'file://...'``. runtime (str) : The runtime(s) to use. E.g. 'app' will open in a desktop-app-like runtime, 'browser' in a browser runtime. One can target specific runtimes, e.g. 'nw-app' or 'edge-browser', or a selection, e.g. 'chrome-browser or firefox-browser'. Default is ``'app or browser'``. See below for more information on available runtimes. kwargs: addition arguments specific to the runtime. See the docs of the runtime classes. Returns: BaseRuntime: An object that represents the runtime. For Desktop runtimes it can be used to close the runtime. Browser runtimes: * browser: open in a browser. Firefox, Chrome and Edge are prefered over the default browser. * default-browser: open in the system default browser. * firefox-browser: open in Firefox browser. * chrome-browser: open in Chrome/Chromium browser. * googlechrome-browser or chromium-browser: like chrome-browser, but specific. * edge-browser: open in Microsoft Edge browser. * ie-browser: open in Microsoft Internet Explorer browser. * xx-browser: use webbrowser module to open in browser "xx". App runtimes: * app: open as desktop app, using firefox-app or nw-app (and chrome-app on Windows). * firerox-app: open as desktop app, using Firefox' app framework (Xul). * nw-app: open as desktop app using NW.js. * chrome-app: open as desktop-like app via Chrome/Chromium (only works well on Windows). * pyqt-app: open as desktop-like app using PyQt/PySide. The most developed app runtimes are Firefox and NW. The former requires the user to have Firefox installed. The latter can be installed by the user simply by downloading the archive. Firefox is lighter (memory-wise), while NW is based on Chromium, making it heavier. The other app runtimes are useful for testing or development, but should generally be avoided when distributing apps. """ # Resolve backward compat names, and select default runtime if not given if runtime in _aliases_compat: logger.warn('Runtime name %s is deprecated, use %s instead.' % (runtime, _aliases_compat[runtime])) runtime = _aliases_compat[runtime] if not runtime: runtime = 'app or browser' given_runtime = runtime # Normalize runtime, apply aliases runtimes = _expand_runtime_name(runtime) tried_runtimes = [] errors = [] # Attempt to launch runtimes, one by one for runtime in runtimes: rt, launched, err = _launch(url, runtime, **kwargs) if rt and launched: return rt # Hooray! if rt: tried_runtimes.append(rt) if err: errors.append(str(err).strip()) # We end up here only when no suitable runtime was found. # Note that default-browser will always work, so by default we wont # end up here. We can well get here when runtime is 'app' though. # Show dialog to the user with information on how to install a runtime. # It is important that this is a dialog and not printed to stdout for # cases where an app is frozen (e.g. with cx_Freeze), because there is # no stdout in that case. Dialite will fallback to stdout if there is no # way to create a dialog, and if there is a tty, and attempt to show a # webpage with an error message otherwise. messages = [] if not tried_runtimes: messages.append('Given runtime name "%s" does ' 'not resolve to any known runtimes.' % given_runtime) elif len(tried_runtimes) == 1: # This app needs exactly this runtime rt = tried_runtimes[0] name = given_runtime if given_runtime.endswith( '-browser') else rt.get_name() msg = 'Could not run app, because runtime %s ' % name msg += 'could not be used.' if errors else 'is not available.' messages.append(msg) if rt._get_install_instuctions(): messages.append(rt._get_install_instuctions()) else: # User has options seen = set() messages.append('Could not find a suitable runtime to run app. ' 'Available options:') for c, rt in zip('ABCDEFGHIJK', tried_runtimes): if rt.get_name() in seen or not rt._get_install_instuctions(): continue seen.add(rt.get_name()) messages.append(c + ': ' + rt._get_install_instuctions()) if errors: messages.append('Errors:') messages.extend(errors) messages = '\n\n'.join(messages) dialite.fail('Webruntime - No suitable runtime available', messages) raise ValueError('Could not detect a suitable backend among %r.' % runtimes)
PREFIX + 'unicode', u'Do you see "double quotes", \'single quotes\', ' u'a euro symbol (€), pi symbol (π), an A with a roof (Â)?') assert res is True # Three message boxes res = dialite.inform( PREFIX + 'info', 'Awesome! ' 'We will now show three dialogs: info, warn, error. ' 'This is the first one; an info dialog.') assert res is None res = dialite.warn(PREFIX + 'warn', 'This is the second one; a warning.') assert res is None res = dialite.fail(PREFIX + 'error', 'This is the third one; an error.') assert res is None # Check results res = dialite.ask_yesno( PREFIX + 'check', 'Did the past three boxes look something like an info, ' 'warning, and error dialog, and have only an OK option?') assert res is True # Check confirm res = dialite.ask_ok( PREFIX + 'confirm', 'Great, I am going to asume all tests passed then!' 'Press OK to continue.') assert res is True