#----------------------------------------------------------------------------- # Copyright (c) 2013-2021, PyInstaller Development Team. # # Distributed under the terms of the GNU General Public License (version 2 # or later) with exception for distributing the bootloader. # # The full license is in the file COPYING.txt, distributed with this software. # # SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception) #----------------------------------------------------------------------------- from PyInstaller.compat import is_darwin from PyInstaller.utils.hooks import eval_statement, exec_statement, logger def get_matplotlib_backend_module_names(): """ List the names of all matplotlib backend modules importable under the current Python installation. Returns ---------- list List of the fully-qualified names of all such modules. """ # Statement safely importing a single backend module. import_statement = """ import os, sys # Preserve stdout. sys_stdout = sys.stdout try: # Redirect output printed by this importation to "/dev/null", preventing such output from being erroneously # interpreted as an error. with open(os.devnull, 'w') as dev_null: sys.stdout = dev_null __import__('%s') # If this is an ImportError, print this exception's message without a traceback. ImportError messages are human-readable # and require no additional context. except ImportError as exc: sys.stdout = sys_stdout print(exc) # Else, print this exception preceded by a traceback. traceback.print_exc() prints to stderr rather than stdout and must # not be called here! except Exception: sys.stdout = sys_stdout import traceback print(traceback.format_exc()) """ # List of the human-readable names of all available backends. backend_names = eval_statement('import matplotlib; print(matplotlib.rcsetup.all_backends)') # List of the fully-qualified names of all importable backend modules. module_names = [] # If the current system is not OS X and the "CocoaAgg" backend is available, remove this backend from consideration. # Attempting to import this backend on non-OS X systems halts the current subprocess without printing output or # raising exceptions, preventing its reliable detection. if not is_darwin and 'CocoaAgg' in backend_names: backend_names.remove('CocoaAgg') # For safety, attempt to import each backend in a unique subprocess. for backend_name in backend_names: module_name = 'matplotlib.backends.backend_%s' % backend_name.lower() stdout = exec_statement(import_statement % module_name) # If no output was printed, this backend is importable. if not stdout: module_names.append(module_name) logger.info(' Matplotlib backend "%s": added' % backend_name) else: logger.info(' Matplotlib backend "%s": ignored\n %s' % (backend_name, stdout)) return module_names # Freeze all importable backends, as PyInstaller is unable to determine exactly which backends are required by the # current program. hiddenimports = get_matplotlib_backend_module_names()