def main(): """ Entry point for GNS3 GUI. """ # Sometimes (for example at first launch) the OSX app service launcher add # an extra argument starting with -psn_. We filter it if sys.platform.startswith("darwin"): sys.argv = [a for a in sys.argv if not a.startswith("-psn_")] parser = argparse.ArgumentParser() parser.add_argument("project", help="load a GNS3 project (.gns3)", metavar="path", nargs="?") parser.add_argument("--version", help="show the version", action="version", version=__version__) parser.add_argument("--debug", help="print out debug messages", action="store_true", default=False) parser.add_argument("--config", help="Configuration file") options = parser.parse_args() exception_file_path = "exceptions.log" if options.config: LocalConfig.instance(config_file=options.config) else: LocalConfig.instance() if options.project: options.project = os.path.abspath(options.project) if hasattr(sys, "frozen"): # We add to the path where the OS search executable our binary location starting by GNS3 # packaged binary frozen_dir = os.path.dirname(os.path.abspath(sys.executable)) if sys.platform.startswith("darwin"): frozen_dirs = [ frozen_dir, os.path.normpath(os.path.join(frozen_dir, '..', 'Resources')) ] elif sys.platform.startswith("win"): frozen_dirs = [ frozen_dir, os.path.normpath(os.path.join(frozen_dir, 'dynamips')), os.path.normpath(os.path.join(frozen_dir, 'vpcs')) ] os.environ["PATH"] = os.pathsep.join(frozen_dirs) + os.pathsep + os.environ.get("PATH", "") if options.project: os.chdir(frozen_dir) def exceptionHook(exception, value, tb): if exception == KeyboardInterrupt: sys.exit(0) lines = traceback.format_exception(exception, value, tb) print("****** Exception detected, traceback information saved in {} ******".format(exception_file_path)) print("\nPLEASE REPORT ON https://www.gns3.com\n") print("".join(lines)) try: curdate = time.strftime("%d %b %Y %H:%M:%S") logfile = open(exception_file_path, "a", encoding="utf-8") logfile.write("=== GNS3 {} traceback on {} ===\n".format(__version__, curdate)) logfile.write("".join(lines)) logfile.close() except OSError as e: print("Could not save traceback to {}: {}".format(os.path.normpath(exception_file_path), e)) if not sys.stdout.isatty(): # if stdout is not a tty (redirected to the console view), # then print the exception on stderr too. print("".join(lines), file=sys.stderr) if exception is MemoryError: print("YOUR SYSTEM IS OUT OF MEMORY!") else: CrashReport.instance().captureException(exception, value, tb) # catch exceptions to write them in a file sys.excepthook = exceptionHook current_year = datetime.date.today().year print("GNS3 GUI version {}".format(__version__)) print("Copyright (c) 2007-{} GNS3 Technologies Inc.".format(current_year)) # we only support Python 3 version >= 3.4 if sys.version_info < (3, 4): raise SystemExit("Python 3.4 or higher is required") if parse_version(QtCore.QT_VERSION_STR) < parse_version("5.0.0"): raise SystemExit("Requirement is PyQt5 version 5.0.0 or higher, got version {}".format(QtCore.QT_VERSION_STR)) if parse_version(psutil.__version__) < parse_version("2.2.1"): raise SystemExit("Requirement is psutil version 2.2.1 or higher, got version {}".format(psutil.__version__)) # check for the correct locale # (UNIX/Linux only) locale_check() try: os.getcwd() except FileNotFoundError: log.critical("the current working directory doesn't exist") return # always use the INI format on Windows and OSX (because we don't like the registry and plist files) if sys.platform.startswith('win') or sys.platform.startswith('darwin'): QtCore.QSettings.setDefaultFormat(QtCore.QSettings.IniFormat) if sys.platform.startswith('win') and hasattr(sys, "frozen"): try: import win32console import win32con import win32gui except ImportError: raise SystemExit("Python for Windows extensions must be installed.") if not options.debug: try: # hide the console console_window = win32console.GetConsoleWindow() win32gui.ShowWindow(console_window, win32con.SW_HIDE) except win32console.error as e: print("warning: could not allocate console: {}".format(e)) global app app = Application(sys.argv) # save client logging info to a file logfile = os.path.join(LocalConfig.configDirectory(), "gns3_gui.log") # on debug enable logging to stdout if options.debug: root_logger = init_logger(logging.DEBUG, logfile) else: root_logger = init_logger(logging.INFO, logfile) # update the exception file path to have it in the same directory as the settings file. exception_file_path = os.path.join(LocalConfig.configDirectory(), exception_file_path) global mainwindow mainwindow = MainWindow() # On OSX we can receive the file to open from a system event # loadPath is smart and will load only if a path is present mainwindow.ready_signal.connect(lambda: mainwindow.loadPath(app.open_file_at_startup)) mainwindow.ready_signal.connect(lambda: mainwindow.loadPath(options.project)) app.file_open_signal.connect(lambda path: mainwindow.loadPath(path)) # Manage Ctrl + C or kill command def sigint_handler(*args): log.info("Signal received exiting the application") mainwindow.setSoftExit(False) app.closeAllWindows() orig_sigint = signal.signal(signal.SIGINT, sigint_handler) orig_sigterm = signal.signal(signal.SIGTERM, sigint_handler) mainwindow.show() exit_code = app.exec_() signal.signal(signal.SIGINT, orig_sigint) signal.signal(signal.SIGTERM, orig_sigterm) delattr(MainWindow, "_instance") # We force deleting the app object otherwise it's segfault on Fedora del app # We force a full garbage collect before exit # for unknow reason otherwise Qt Segfault on OSX in some # conditions import gc gc.collect() sys.exit(exit_code)
def main(): """ Entry point for GNS3 GUI. """ # Get Python tracebacks explicitly, on a fault like segfault faulthandler.enable() # Sometimes (for example at first launch) the OSX app service launcher add # an extra argument starting with -psn_. We filter it if sys.platform.startswith("darwin"): sys.argv = [a for a in sys.argv if not a.startswith("-psn_")] if parse_version(QtCore.QT_VERSION_STR) < parse_version("5.15.2"): # Fixes issue on macOS Big Sur: https://github.com/GNS3/gns3-gui/issues/3037 os.environ["QT_MAC_WANTS_LAYER"] = "1" parser = argparse.ArgumentParser() parser.add_argument("project", help="load a GNS3 project (.gns3)", metavar="path", nargs="?") parser.add_argument("--version", help="show the version", action="version", version=__version__) parser.add_argument("--debug", help="print out debug messages", action="store_true", default=False) parser.add_argument("-q", "--quiet", action="store_true", help="do not show logs on stdout") parser.add_argument("--config", help="Configuration file") parser.add_argument("--profile", help="Settings profile (blank will use default settings files)") options = parser.parse_args() exception_file_path = "exceptions.log" if options.project: options.project = os.path.abspath(options.project) if hasattr(sys, "frozen"): # We add to the path where the OS search executable our binary location starting by GNS3 # packaged binary frozen_dir = os.path.dirname(os.path.abspath(sys.executable)) if sys.platform.startswith("darwin"): frozen_dirs = [frozen_dir] elif sys.platform.startswith("win"): frozen_dirs = [ frozen_dir, os.path.normpath(os.path.join(frozen_dir, 'dynamips')), os.path.normpath(os.path.join(frozen_dir, 'vpcs')), os.path.normpath(os.path.join(frozen_dir, 'traceng')) ] os.environ["PATH"] = os.pathsep.join(frozen_dirs) + os.pathsep + os.environ.get("PATH", "") if options.project: os.chdir(frozen_dir) def exceptionHook(exception, value, tb): if exception == KeyboardInterrupt: sys.exit(0) lines = traceback.format_exception(exception, value, tb) print("****** Exception detected, traceback information saved in {} ******".format(exception_file_path)) print("\nPLEASE REPORT ON https://www.gns3.com\n") print("".join(lines)) try: curdate = time.strftime("%d %b %Y %H:%M:%S") logfile = open(exception_file_path, "a", encoding="utf-8") logfile.write("=== GNS3 {} traceback on {} ===\n".format(__version__, curdate)) logfile.write("".join(lines)) logfile.close() except OSError as e: print("Could not save traceback to {}: {}".format(os.path.normpath(exception_file_path), e)) if not sys.stdout.isatty(): # if stdout is not a tty (redirected to the console view), # then print the exception on stderr too. print("".join(lines), file=sys.stderr) if exception is MemoryError: print("YOUR SYSTEM IS OUT OF MEMORY!") else: CrashReport.instance().captureException(exception, value, tb) # catch exceptions to write them in a file sys.excepthook = exceptionHook # we only support Python 3 version >= 3.4 if sys.version_info < (3, 4): raise SystemExit("Python 3.4 or higher is required") if parse_version(QtCore.QT_VERSION_STR) < parse_version("5.5.0"): raise SystemExit("Requirement is PyQt5 version 5.5.0 or higher, got version {}".format(QtCore.QT_VERSION_STR)) if parse_version(psutil.__version__) < parse_version("2.2.1"): raise SystemExit("Requirement is psutil version 2.2.1 or higher, got version {}".format(psutil.__version__)) # check for the correct locale # (UNIX/Linux only) locale_check() try: os.getcwd() except FileNotFoundError: log.critical("the current working directory doesn't exist") return # always use the INI format on Windows and OSX (because we don't like the registry and plist files) if sys.platform.startswith('win') or sys.platform.startswith('darwin'): QtCore.QSettings.setDefaultFormat(QtCore.QSettings.IniFormat) if sys.platform.startswith('win') and hasattr(sys, "frozen"): try: import win32console import win32con import win32gui except ImportError: raise SystemExit("Python for Windows extensions must be installed.") if not options.debug: try: # hide the console console_window = win32console.GetConsoleWindow() win32gui.ShowWindow(console_window, win32con.SW_HIDE) except win32console.error as e: print("warning: could not allocate console: {}".format(e)) local_config = LocalConfig.instance() global app app = Application(sys.argv, hdpi=local_config.hdpi()) if local_config.multiProfiles() and not options.profile: profile_select = ProfileSelectDialog() profile_select.show() if profile_select.exec_(): options.profile = profile_select.profile() else: sys.exit(0) # Init the config if options.config: local_config.setConfigFilePath(options.config) elif options.profile: local_config.setProfile(options.profile) # save client logging info to a file logfile = os.path.join(LocalConfig.instance().configDirectory(), "gns3_gui.log") # on debug enable logging to stdout if options.debug: init_logger(logging.DEBUG, logfile) elif options.quiet: init_logger(logging.ERROR, logfile) else: init_logger(logging.INFO, logfile) current_year = datetime.date.today().year log.info("GNS3 GUI version {}".format(__version__)) log.info("Copyright (c) 2007-{} GNS3 Technologies Inc.".format(current_year)) log.info("Application started with {}".format(" ".join(sys.argv))) # update the exception file path to have it in the same directory as the settings file. exception_file_path = os.path.join(LocalConfig.instance().configDirectory(), exception_file_path) # We disallow to run GNS3 from outside the /Applications folder to avoid # issue when people run GNS3 from the .dmg if sys.platform.startswith("darwin") and hasattr(sys, "frozen"): if not os.path.realpath(sys.executable).startswith("/Applications"): error_message = "GNS3.app must be moved to the '/Applications' folder before it can be used" QtWidgets.QMessageBox.critical(False, "Loading error", error_message) QtCore.QTimer.singleShot(0, app.quit) app.exec_() sys.exit(1) global mainwindow startup_file = app.open_file_at_startup if not startup_file: startup_file = options.project mainwindow = MainWindow(open_file=startup_file) # On OSX we can receive the file to open from a system event # loadPath is smart and will load only if a path is present app.file_open_signal.connect(lambda path: mainwindow.loadPath(path)) # Manage Ctrl + C or kill command def sigint_handler(*args): log.info("Signal received exiting the application") app.closeAllWindows() orig_sigint = signal.signal(signal.SIGINT, sigint_handler) orig_sigterm = signal.signal(signal.SIGTERM, sigint_handler) mainwindow.show() exit_code = app.exec_() signal.signal(signal.SIGINT, orig_sigint) signal.signal(signal.SIGTERM, orig_sigterm) delattr(MainWindow, "_instance") # We force deleting the app object otherwise it's segfault on Fedora del app # We force a full garbage collect before exit # for unknown reason otherwise Qt Segfault on OSX in some # conditions import gc gc.collect() sys.exit(exit_code)
def main(): """ Entry point for GNS3 GUI. """ parser = argparse.ArgumentParser() parser.add_argument("project", help="load a GNS3 project (.gns3)", metavar="path", nargs="?") parser.add_argument("--version", help="show the version", action="version", version=__version__) parser.add_argument("--debug", help="print out debug messages", action="store_true", default=False) options = parser.parse_args() exception_file_path = "exceptions.log" if options.project and hasattr(sys, "frozen"): os.chdir(os.path.dirname(os.path.abspath(sys.executable))) def exceptionHook(exception, value, tb): if exception == KeyboardInterrupt: sys.exit(0) lines = traceback.format_exception(exception, value, tb) print("****** Exception detected, traceback information saved in {} ******".format(exception_file_path)) print("\nPLEASE REPORT ON https://www.gns3.com\n") print("".join(lines)) try: curdate = time.strftime("%d %b %Y %H:%M:%S") logfile = open(exception_file_path, "a", encoding="utf-8") logfile.write("=== GNS3 {} traceback on {} ===\n".format(__version__, curdate)) logfile.write("".join(lines)) logfile.close() except OSError as e: print("Could not save traceback to {}: {}".format(os.path.normpath(exception_file_path), e)) if not sys.stdout.isatty(): # if stdout is not a tty (redirected to the console view), # then print the exception on stderr too. print("".join(lines), file=sys.stderr) if exception is MemoryError: print("YOUR SYSTEM IS OUT OF MEMORY!") else: CrashReport.instance().captureException(exception, value, tb) # catch exceptions to write them in a file sys.excepthook = exceptionHook current_year = datetime.date.today().year print("GNS3 GUI version {}".format(__version__)) print("Copyright (c) 2007-{} GNS3 Technologies Inc.".format(current_year)) # we only support Python 2 version >= 2.7 and Python 3 version >= 3.3 if sys.version_info < (2, 7): raise RuntimeError("Python 2.7 or higher is required") elif sys.version_info[0] == 3 and sys.version_info < (3, 3): raise RuntimeError("Python 3.3 or higher is required") def version(version_string): return [int(i) for i in version_string.split('.')] if version(QtCore.QT_VERSION_STR) < version("4.6"): raise RuntimeError("Requirement is Qt version 4.6 or higher, got version {}".format(QtCore.QT_VERSION_STR)) # 4.8.3 because of QSettings (http://pyqt.sourceforge.net/Docs/PyQt4/pyqt_qsettings.html) if DEFAULT_BINDING == "PyQt" and version(QtCore.BINDING_VERSION_STR) < version("4.8.3"): raise RuntimeError("Requirement is PyQt version 4.8.3 or higher, got version {}".format(QtCore.BINDING_VERSION_STR)) if DEFAULT_BINDING == "PySide" and version(QtCore.BINDING_VERSION_STR) < version("1.0"): raise RuntimeError("Requirement is PySide version 1.0 or higher, got version {}".format(QtCore.BINDING_VERSION_STR)) # check for the correct locale # (UNIX/Linux only) locale_check() try: os.getcwd() except FileNotFoundError: log.critical("the current working directory doesn't exist") return # always use the INI format on Windows and OSX (because we don't like the registry and plist files) if sys.platform.startswith('win') or sys.platform.startswith('darwin'): QtCore.QSettings.setDefaultFormat(QtCore.QSettings.IniFormat) if sys.platform.startswith('win') and hasattr(sys, "frozen"): try: import win32console import win32con import win32gui except ImportError: raise RuntimeError("Python for Windows extensions must be installed.") if not options.debug: try: # hide the console console_window = win32console.GetConsoleWindow() win32gui.ShowWindow(console_window, win32con.SW_HIDE) except win32console.error as e: print("warning: could not allocate console: {}".format(e)) app = QtGui.QApplication(sys.argv) # this info is necessary for QSettings app.setOrganizationName("GNS3") app.setOrganizationDomain("gns3.net") app.setApplicationName("GNS3") app.setApplicationVersion(__version__) formatter = logging.Formatter("[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d] %(message)s", datefmt="%y%m%d %H:%M:%S") # on debug enable logging to stdout if options.debug: root_logger = init_logger(logging.DEBUG) else: root_logger = init_logger(logging.INFO) # save client logging info to a file logfile = os.path.join(os.path.dirname(QtCore.QSettings().fileName()), "gns3_gui.log") try: try: os.makedirs(os.path.dirname(QtCore.QSettings().fileName())) except FileExistsError: pass handler = logging.FileHandler(logfile, "w") root_logger.addHandler(handler) except OSError as e: log.warn("could not log to {}: {}".format(logfile, e)) log.info('Log level: {}'.format(logging.getLevelName(log.getEffectiveLevel()))) # update the exception file path to have it in the same directory as the settings file. exception_file_path = os.path.join(os.path.dirname(QtCore.QSettings().fileName()), exception_file_path) mainwindow = MainWindow(options.project) mainwindow.show() exit_code = app.exec_() delattr(MainWindow, "_instance") app.deleteLater() sys.exit(exit_code)
def main(): """ Entry point for GNS3 GUI. """ # Sometimes (for example at first launch) the OSX app service launcher add # an extra argument starting with -psn_. We filter it if sys.platform.startswith("darwin"): sys.argv = [a for a in sys.argv if not a.startswith("-psn_")] parser = argparse.ArgumentParser() parser.add_argument("project", help="load a GNS3 project (.gns3)", metavar="path", nargs="?") parser.add_argument("--version", help="show the version", action="version", version=__version__) parser.add_argument("--debug", help="print out debug messages", action="store_true", default=False) parser.add_argument("--config", help="Configuration file") options = parser.parse_args() exception_file_path = "exceptions.log" if options.config: LocalConfig.instance(config_file=options.config) else: LocalConfig.instance() if hasattr(sys, "frozen"): # We add to the path where the OS search executable our binary location starting by GNS3 # packaged binary frozen_dir = os.path.dirname(os.path.abspath(sys.executable)) if sys.platform.startswith("darwin"): frozen_dirs = [ frozen_dir, os.path.normpath(os.path.join(frozen_dir, '..', 'Resources')) ] elif sys.platform.startswith("win"): frozen_dirs = [ frozen_dir, os.path.normpath(os.path.join(frozen_dir, 'dynamips')), os.path.normpath(os.path.join(frozen_dir, 'vpcs')) ] os.environ["PATH"] = os.pathsep.join( frozen_dirs) + os.pathsep + os.environ.get("PATH", "") if options.project: options.project = os.path.abspath(options.project) os.chdir(frozen_dir) def exceptionHook(exception, value, tb): if exception == KeyboardInterrupt: sys.exit(0) lines = traceback.format_exception(exception, value, tb) print( "****** Exception detected, traceback information saved in {} ******" .format(exception_file_path)) print("\nPLEASE REPORT ON https://www.gns3.com\n") print("".join(lines)) try: curdate = time.strftime("%d %b %Y %H:%M:%S") logfile = open(exception_file_path, "a", encoding="utf-8") logfile.write("=== GNS3 {} traceback on {} ===\n".format( __version__, curdate)) logfile.write("".join(lines)) logfile.close() except OSError as e: print("Could not save traceback to {}: {}".format( os.path.normpath(exception_file_path), e)) if not sys.stdout.isatty(): # if stdout is not a tty (redirected to the console view), # then print the exception on stderr too. print("".join(lines), file=sys.stderr) if exception is MemoryError: print("YOUR SYSTEM IS OUT OF MEMORY!") else: CrashReport.instance().captureException(exception, value, tb) # catch exceptions to write them in a file sys.excepthook = exceptionHook current_year = datetime.date.today().year print("GNS3 GUI version {}".format(__version__)) print("Copyright (c) 2007-{} GNS3 Technologies Inc.".format(current_year)) # we only support Python 3 version >= 3.4 if sys.version_info < (3, 4): raise SystemExit("Python 3.4 or higher is required") def version(version_string): result = [] for i in re.split(r'[^0-9]', version_string): if len(i): result.append(int(i)) return result # 4.8.3 because of QSettings (http://pyqt.sourceforge.net/Docs/PyQt4/pyqt_qsettings.html) if DEFAULT_BINDING == "PyQt4" and version( QtCore.BINDING_VERSION_STR) < version("4.8.3"): raise SystemExit( "Requirement is PyQt version 4.8.3 or higher, got version {}". format(QtCore.BINDING_VERSION_STR)) if DEFAULT_BINDING == "PyQt5" and version( QtCore.BINDING_VERSION_STR) < version("5.0.0"): raise SystemExit( "Requirement is PyQt5 version 5.0.0 or higher, got version {}". format(QtCore.BINDING_VERSION_STR)) import psutil if version(psutil.__version__) < version("2.2.1"): raise SystemExit( "Requirement is psutil version 2.2.1 or higher, got version {}". format(psutil.__version__)) # check for the correct locale # (UNIX/Linux only) locale_check() try: os.getcwd() except FileNotFoundError: log.critical("the current working directory doesn't exist") return # always use the INI format on Windows and OSX (because we don't like the registry and plist files) if sys.platform.startswith('win') or sys.platform.startswith('darwin'): QtCore.QSettings.setDefaultFormat(QtCore.QSettings.IniFormat) if sys.platform.startswith('win') and hasattr(sys, "frozen"): try: import win32console import win32con import win32gui except ImportError: raise SystemExit( "Python for Windows extensions must be installed.") if not options.debug: try: # hide the console console_window = win32console.GetConsoleWindow() win32gui.ShowWindow(console_window, win32con.SW_HIDE) except win32console.error as e: print("warning: could not allocate console: {}".format(e)) global app app = Application(sys.argv) # save client logging info to a file logfile = os.path.join(LocalConfig.configDirectory(), "gns3_gui.log") # on debug enable logging to stdout if options.debug: root_logger = init_logger(logging.DEBUG, logfile) else: root_logger = init_logger(logging.INFO, logfile) # update the exception file path to have it in the same directory as the settings file. exception_file_path = os.path.join(LocalConfig.configDirectory(), exception_file_path) global mainwindow mainwindow = MainWindow() # On OSX we can receive the file to open from a system event # loadPath is smart and will load only if a path is present mainwindow.ready_signal.connect( lambda: mainwindow.loadPath(app.open_file_at_startup)) mainwindow.ready_signal.connect( lambda: mainwindow.loadPath(options.project)) app.file_open_signal.connect(lambda path: mainwindow.loadPath(path)) # Manage Ctrl + C or kill command def sigint_handler(*args): log.info("Signal received exiting the application") mainwindow.setSoftExit(False) app.closeAllWindows() signal.signal(signal.SIGINT, sigint_handler) signal.signal(signal.SIGTERM, sigint_handler) mainwindow.show() exit_code = app.exec_() delattr(MainWindow, "_instance") # We force a full garbage collect before exit # for unknow reason otherwise Qt Segfault on OSX in some # conditions import gc gc.collect() sys.exit(exit_code)
def main(): """ Entry point for GNS3 GUI. """ parser = argparse.ArgumentParser() parser.add_argument("project", help="load a GNS3 project (.gns3)", metavar="path", nargs="?") parser.add_argument("--version", help="show the version", action="version", version=__version__) parser.add_argument("--debug", help="print out debug messages", action="store_true", default=False) options = parser.parse_args() exception_file_path = "exceptions.log" if options.project and hasattr(sys, "frozen"): os.chdir(os.path.dirname(os.path.abspath(sys.executable))) def exceptionHook(exception, value, tb): if exception == KeyboardInterrupt: sys.exit(0) lines = traceback.format_exception(exception, value, tb) print( "****** Exception detected, traceback information saved in {} ******" .format(exception_file_path)) print( "\nPLEASE REPORT ON https://community.gns3.com/community/support/bug\n" ) print("".join(lines)) try: curdate = time.strftime("%d %b %Y %H:%M:%S") logfile = open(exception_file_path, "a") logfile.write("=== GNS3 {} traceback on {} ===\n".format( __version__, curdate)) logfile.write("".join(lines)) logfile.close() except OSError as e: print("Could not save traceback to {}: {}".format( os.path.normpath(exception_file_path), e)) if not sys.stdout.isatty(): # if stdout is not a tty (redirected to the console view), # then print the exception on stderr too. print("".join(lines), file=sys.stderr) CrashReport.instance().captureException(exception, value, tb) # catch exceptions to write them in a file sys.excepthook = exceptionHook current_year = datetime.date.today().year print("GNS3 GUI version {}".format(__version__)) print("Copyright (c) 2007-{} GNS3 Technologies Inc.".format(current_year)) # we only support Python 2 version >= 2.7 and Python 3 version >= 3.3 if sys.version_info < (2, 7): raise RuntimeError("Python 2.7 or higher is required") elif sys.version_info[0] == 3 and sys.version_info < (3, 3): raise RuntimeError("Python 3.3 or higher is required") def version(version_string): return [int(i) for i in version_string.split('.')] if version(QtCore.QT_VERSION_STR) < version("4.6"): raise RuntimeError( "Requirement is Qt version 4.6 or higher, got version {}".format( QtCore.QT_VERSION_STR)) # 4.8.3 because of QSettings (http://pyqt.sourceforge.net/Docs/PyQt4/pyqt_qsettings.html) if DEFAULT_BINDING == "PyQt" and version( QtCore.BINDING_VERSION_STR) < version("4.8.3"): raise RuntimeError( "Requirement is PyQt version 4.8.3 or higher, got version {}". format(QtCore.BINDING_VERSION_STR)) if DEFAULT_BINDING == "PySide" and version( QtCore.BINDING_VERSION_STR) < version("1.0"): raise RuntimeError( "Requirement is PySide version 1.0 or higher, got version {}". format(QtCore.BINDING_VERSION_STR)) # check for the correct locale # (UNIX/Linux only) locale_check() try: os.getcwd() except FileNotFoundError: log.critical("the current working directory doesn't exist") return # always use the INI format on Windows and OSX (because we don't like the registry and plist files) if sys.platform.startswith('win') or sys.platform.startswith('darwin'): QtCore.QSettings.setDefaultFormat(QtCore.QSettings.IniFormat) if sys.platform.startswith('win') and hasattr(sys, "frozen"): try: import win32console import win32con import win32gui except ImportError: raise RuntimeError( "Python for Windows extensions must be installed.") if not options.debug: try: # hide the console console_window = win32console.GetConsoleWindow() win32gui.ShowWindow(console_window, win32con.SW_HIDE) except win32console.error as e: print("warning: could not allocate console: {}".format(e)) app = QtGui.QApplication(sys.argv) # this info is necessary for QSettings app.setOrganizationName("GNS3") app.setOrganizationDomain("gns3.net") app.setApplicationName("GNS3") app.setApplicationVersion(__version__) formatter = logging.Formatter( "[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d] %(message)s", datefmt="%y%m%d %H:%M:%S") # on debug enable logging to stdout if options.debug: root_logger = init_logger(logging.DEBUG) else: root_logger = init_logger(logging.INFO) # save client logging info to a file logfile = os.path.join(os.path.dirname(QtCore.QSettings().fileName()), "gns3_gui.log") try: try: os.makedirs(os.path.dirname(QtCore.QSettings().fileName())) except FileExistsError: pass handler = logging.FileHandler(logfile, "w") root_logger.addHandler(handler) except OSError as e: log.warn("could not log to {}: {}".format(logfile, e)) log.info('Log level: {}'.format( logging.getLevelName(log.getEffectiveLevel()))) # update the exception file path to have it in the same directory as the settings file. exception_file_path = os.path.join( os.path.dirname(QtCore.QSettings().fileName()), exception_file_path) mainwindow = MainWindow(options.project) mainwindow.show() exit_code = app.exec_() delattr(MainWindow, "_instance") app.deleteLater() sys.exit(exit_code)