示例#1
0
def _find_tcl_tk_dir():
    """
    Get a platform-agnostic 2-tuple of the absolute paths of the top-level
    external data directories for both Tcl and Tk, respectively.

    Returns
    -------
    list
        2-tuple whose first element is the value of `${TCL_LIBRARY}` and whose
        second element is the value of `${TK_LIBRARY}`.
    """
    # Python code to get path to TCL_LIBRARY.
    tcl_root = exec_statement(
        'from %s import Tcl; print(Tcl().eval("info library"))' % modname_tkinter)
    tk_version = exec_statement(
        'from _tkinter import TK_VERSION; print(TK_VERSION)')

    # TK_LIBRARY is in the same prefix as Tcl.
    tk_root = os.path.join(os.path.dirname(tcl_root), 'tk%s' % tk_version)
    return tcl_root, tk_root
示例#2
0
def qt4_phonon_plugins_dir():
    import os
    qt4_plugin_dirs = eval(exec_statement("from PySide.QtGui import QApplication; app=QApplication([]); app.setApplicationName('pyinstaller'); from PySide.phonon import Phonon; v=Phonon.VideoPlayer(Phonon.VideoCategory); print map(unicode,app.libraryPaths())"))
    if not qt4_plugin_dirs:
        print "E: Cannot find PySide phonon plugin directories"
        return ""
    for d in qt4_plugin_dirs:
        if os.path.isdir(d):
            return str(d)  # must be 8-bit chars for one-file builds
    print "E: Cannot find existing PySide phonon plugin directory"
    return ""
示例#3
0
def _module_path(mod):
    return  exec_statement(
        """
        import sys
        import os;
        _tmp = sys.stdout
        sys.stdout = open(os.devnull,"w")
        sys.stderr = open(os.devnull,"w")
        import %s;
        sys.stdout = _tmp
        print(os.path.dirname(%s.__file__))
        """%(mod, mod))
示例#4
0
# -----------------------------------------------------------------------------
# Copyright (c) 2013-2019, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License with exception
# for distributing bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
# -----------------------------------------------------------------------------

from PyInstaller.utils.hooks import exec_statement

mpl_data_dir = exec_statement(
    "import matplotlib; print(matplotlib._get_data_path())")

datas = [
    (mpl_data_dir, "mpl-data"),
]
示例#5
0
from PyInstaller.utils.hooks import exec_statement
#from PyInstaller.build import Tree

pandas_path = exec_statement("import pandas; print pandas.__path__[0]")
print pandas_path

#dict_tree = Tree(pandas_path, prefix='pandas', excludes=["*.pyc"])
#datas = dict_tree
#binaries = filter(lambda x: 'pandas' not in x[0], binaries)
示例#6
0

hiddenimports = ['gi.overrides.Gio']


datas = get_typelibs('Gio', '2.0')


binaries = []

statement = """
from gi.repository import Gio
print(Gio.__path__)
"""

path = exec_statement(statement)
pattern = None

if is_darwin:
    # Use commonprefix to find common prefix between sys.prefix and the path, e.g.,
    # /opt/local/Library/Frameworks/Python.framework/Versions/3.4,
    # and /opt/local/lib/girepository-1.0/Gio-2.0.typelib.
    # Then use that and the standard Gio modules path of <prefix>/lib/gio/modules/ to gather the modules.
    pattern = os.path.join(os.path.commonprefix([sys.prefix, path]), 'lib', 'gio', 'modules', '*.so')
elif is_win:
    # Don't use common prefix since sys.prefix on Windows in usually C:\Python<version> and Gio's modules
    # are installed at C:\Python<version>\Lib\site-packages\gnome\lib\gio\modules which wouldn't yield a useful prefix.
    # By just backing up a directory level from the Gio typelib we are then in the gnome lib directory and can then
    # use the standard Gio modules path to gather the modules.
    pattern = os.path.join(os.path.dirname(path), '..', 'gio', 'modules', '*.dll')
示例#7
0
#-----------------------------------------------------------------------------
# Copyright (c) 2013-2019, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License with exception
# for distributing bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------

from PyInstaller.utils.hooks import exec_statement

# This needed because comtypes wx.lib.activex generates some stuff.
exec_statement("import wx.lib.activex")
示例#8
0
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------

import os
from pkg_resources import Requirement

from PyInstaller.utils.hooks import qt5_menu_nib_dir, exec_statement
from PyInstaller.compat import getsitepackages, is_darwin, is_win

# On Windows system PATH has to be extended to point to the PyQt5 directory.
# The PySide directory contains Qt dlls. We need to avoid including different
# version of Qt libraries when there is installed another application (e.g. QtCreator)
if is_win:
    from PyInstaller.utils.win32.winutils import extend_system_path
    extend_system_path([os.path.join(x, 'PyQt5') for x in getsitepackages()])

# In the new consolidated mode any PyQt depends on _qt
hiddenimports = ['sip', 'PyQt5.Qt']

# For Qt<5.4 to work on Mac OS X it is necessary to include `qt_menu.nib`.
# This directory contains some resource files necessary to run PyQt or PySide
# app.
qt_version = exec_statement("""
from PyQt5.QtCore import QT_VERSION_STR
print(QT_VERSION_STR)
""")
if is_darwin and qt_version in Requirement.parse("QT<5.4"):
    datas = [
        (qt5_menu_nib_dir(), ''),
    ]
示例#9
0
# Copyright (c) 2013, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License with exception
# for distributing bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------


from PyInstaller.utils.hooks import exec_statement, is_module_version

# include most common database bindings
# some database bindings are detected and include some
# are not. We should explicitly include database backends.
hiddenimports = ['pysqlite2', 'MySQLdb', 'psycopg2']

# sqlalchemy.dialects package from 0.6 and newer sqlachemy versions
if is_module_version('sqlalchemy', '>=', '0.6'):
    dialects = exec_statement("import sqlalchemy.dialects;print(sqlalchemy.dialects.__all__)")
    dialects = eval(dialects.strip())

    for n in dialects:
        hiddenimports.append("sqlalchemy.dialects." + n)
else:
    # sqlalchemy.databases package from pre 0.6 sqlachemy versions
    databases = exec_statement("import sqlalchemy.databases; print(sqlalchemy.databases.__all__)")
    databases = eval(databases.strip())

    for n in databases:
        hiddenimports.append("sqlalchemy.databases." + n)
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
示例#11
0
datas += collect_glib_share_files('gstreamer-1.0')

hiddenimports += ["gi.repository.Gio"]

for prog in [
        'gst-plugins-bad-1.0', 'gst-plugins-base-1.0', 'gst-plugins-good-1.0',
        'gst-plugins-ugly-1.0', 'gstreamer-1.0'
]:
    datas += collect_glib_translations(prog)

statement = """
import os
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst
Gst.init(None)
reg = Gst.Registry.get()
plug = reg.find_plugin('coreelements')
path = plug.get_filename()
print(os.path.dirname(path))
"""

plugin_path = exec_statement(statement)

# Use a pattern of libgst* since all GStreamer plugins that conform to GStreamer standards start with libgst
# and we may have mixed plugin extensions, e.g., .so and .dylib.
for pattern in ['libgst*.dll', 'libgst*.dylib', 'libgst*.so']:
    pattern = os.path.join(plugin_path, pattern)
    binaries += [(f, os.path.join('gst_plugins')) for f in glob.glob(pattern)]
示例#12
0
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA

# Contributed by Greg Copeland

from PyInstaller.utils.hooks import exec_statement

# include most common database bindings
# some database bindings are detected and include some
# are not. We should explicitly include database backends.
hiddenimports = ['pysqlite2', 'MySQLdb']#, 'psycopg2', 'pyodbc', 'pymysql']

# print ("in custom sql alchemy hook ")

# sqlalchemy.databases package from pre 0.6 sqlachemy versions
databases = exec_statement("import sqlalchemy.databases;print sqlalchemy.databases.__all__")
try:
    databases = eval(databases.strip())

    for n in databases:
        hiddenimports.append("sqlalchemy.databases." + n)
except:
    print ("No databases found")

for n in databases:
    hiddenimports.append("sqlalchemy.databases." + n)

# sqlalchemy.orm package from pre 0.6 sqlachemy versions
orm = exec_statement("import sqlalchemy.orm;print sqlalchemy.orm.__all__")
orm = eval(orm.strip())
示例#13
0
from PyInstaller.lib.modulegraph.util import guess_encoding
from PyInstaller.utils.hooks import exec_statement, is_module_satisfies, logger

# 'sqlalchemy.testing' causes bundling a lot of unnecessary modules.
excludedimports = ['sqlalchemy.testing']

# Include most common database bindings some database bindings are detected and include some are not. We should
# explicitly include database backends.
hiddenimports = ['pysqlite2', 'MySQLdb', 'psycopg2', 'sqlalchemy.ext.baked']

if is_module_satisfies('sqlalchemy >= 1.4'):
    hiddenimports.append("sqlalchemy.sql.default_comparator")

# In SQLAlchemy >= 0.6, the "sqlalchemy.dialects" package provides dialects.
if is_module_satisfies('sqlalchemy >= 0.6'):
    dialects = exec_statement(
        "import sqlalchemy.dialects;print(sqlalchemy.dialects.__all__)")
    dialects = eval(dialects.strip())

    for n in dialects:
        hiddenimports.append("sqlalchemy.dialects." + n)
# In SQLAlchemy <= 0.5, the "sqlalchemy.databases" package provides dialects.
else:
    databases = exec_statement(
        "import sqlalchemy.databases; print(sqlalchemy.databases.__all__)")
    databases = eval(databases.strip())

    for n in databases:
        hiddenimports.append("sqlalchemy.databases." + n)


def hook(hook_api):
#
# SPDX-License-Identifier: GPL-2.0-or-later
# ------------------------------------------------------------------
import json
from PyInstaller.utils.hooks import exec_statement

hiddenimports = [
    "sentry_sdk.integrations.stdlib", "sentry_sdk.integrations.excepthook",
    "sentry_sdk.integrations.dedupe", "sentry_sdk.integrations.atexit",
    "sentry_sdk.integrations.modules", "sentry_sdk.integrations.argv",
    "sentry_sdk.integrations.logging", "sentry_sdk.integrations.threading"
]

statement = """
import json
import sentry_sdk.integrations as si

integrations = []
if hasattr(si, '_AUTO_ENABLING_INTEGRATIONS'):
    # _AUTO_ENABLING_INTEGRATIONS is a list of strings with default enabled integrations
    # https://github.com/getsentry/sentry-python/blob/c6b6f2086b58ffc674df5c25a600b8a615079fb5/sentry_sdk/integrations/__init__.py#L54-L66

    def make_integration_name(integration_name: str):
        return integration_name.rsplit(".", maxsplit=1)[0]

    integrations.extend(map(make_integration_name, si._AUTO_ENABLING_INTEGRATIONS))
print(json.dumps(integrations))
"""

hiddenimports.extend(json.loads(exec_statement(statement)))
示例#15
0
def collect_submodules_traitsui(package, filter=lambda name: True):
    # Accept only strings as packages.
    if not isinstance(package, string_types):
        raise ValueError

    logger.debug('Collecting submodules for %s' % package)
    # Skip a module which is not a package.
    if not is_package(package):
        logger.debug('collect_submodules - Module %s is not a package.' % package)
        return []

    # Determine the filesystem path to the specified package.
    pkg_base, pkg_dir = get_package_paths(package)

    # Walk the package. Since this performs imports, do it in a separate
    # process.
    names = exec_statement("""
        import sys
        import pkgutil

        def ignore_err(name, err):
            # Can't print anything because printing is captured as module names
            # print ("error importing %s: %s" % (name, err))
            pass

        # ``pkgutil.walk_packages`` doesn't walk subpackages of zipped files
        # per https://bugs.python.org/issue14209. This is a workaround.
        def walk_packages(path=None, prefix='', onerror=ignore_err):
            def seen(p, m={{}}):
                if p in m:
                    return True
                m[p] = True

            for importer, name, ispkg in pkgutil.iter_modules(path, prefix):
                if not name.startswith(prefix):   ## Added
                    name = prefix + name          ## Added
                yield importer, name, ispkg

                if ispkg:
                    try:
                        __import__(name)
                    except ImportError as e:
                        if onerror is not None:
                            onerror(name, e)
                    except Exception as e:
                        if onerror is not None:
                            onerror(name, e)
                        else:
                            raise
                    else:
                        path = getattr(sys.modules[name], '__path__', None) or []

                        # don't traverse path items we've seen before
                        path = [p for p in path if not seen(p)]

                        ## Use Py2 code here. It still works in Py3.
                        for item in walk_packages(path, name+'.', onerror):
                            yield item
                        ## This is the original Py3 code.
                        #yield from walk_packages(path, name+'.', onerror)

        for module_loader, name, ispkg in walk_packages([{}], '{}.'):
            print(name)
        """.format(
                  # Use repr to escape Windows backslashes.
                  repr(pkg_dir), package))

    # Include the package itself in the results.
    mods = {package}
    # Filter through the returend submodules.
    for name in names.split():
        if filter(name):
            mods.add(name)

    logger.debug("collect_submodules - Found submodules: %s", mods)
    return list(mods)
from PyInstaller.utils.hooks import exec_statement, collect_submodules

strptime_data_file = exec_statement(
"import inspect; import _strptime; print(inspect.getfile(_strptime))"
)

datas = [ (strptime_data_file, ".") ]

hiddenimports = collect_submodules('dateparser')
示例#17
0
文件: qt.py 项目: Doringber/blog
    def __getattr__(self, name):
        if 'version' in self.__dict__:
            # Initialization was already done, but requested attribute is not
            # availiable.
            raise AttributeError(name)
        else:
            # Ensure self.version exists, even if PyQt{5,6}/PySide{2,6} cannot
            # be imported. Hooks and util functions use `if .version` to check
            # whether package was imported and other attributes are
            # expected to be available.  This also serves as a marker that
            # initialization was already done.
            self.version = None
            # Get library path information from Qt. See QLibraryInfo_.
            json_str = hooks.exec_statement("""
                import sys

                # exec_statement only captures stdout. If there are
                # errors, capture them to stdout so they can be displayed to the
                # user. Do this early, in case package imports produce stderr
                # output.
                sys.stderr = sys.stdout

                import json
                try:
                    from %s.QtCore import QLibraryInfo, QCoreApplication
                except Exception:
                    print('False')
                    raise SystemExit(0)

                # QLibraryInfo isn't always valid until a QCoreApplication is
                # instantiated.
                app = QCoreApplication(sys.argv)
                # Qt6 deprecated QLibraryInfo.location() in favor of
                # QLibraryInfo.path(), and QLibraryInfo.LibraryLocation
                # enum was replaced by QLibraryInfo.LibraryPath.
                if hasattr(QLibraryInfo, 'path'):
                    # Qt6; enumerate path enum values directly from
                    # the QLibraryInfo.LibraryPath enum.
                    path_names = [x for x in dir(QLibraryInfo.LibraryPath)
                                  if x.endswith('Path')]
                    location = {x: QLibraryInfo.path(
                                getattr(QLibraryInfo.LibraryPath, x))
                                for x in path_names}
                else:
                    # Qt5; in recent versions, location enum values
                    # can be enumeratd from QLibraryInfo.LibraryLocation.
                    # However, in older versions of Qt5 and its python
                    # bindings, that is unavailable. Hence the enumeration
                    # of "*Path"-named members of QLibraryInfo.
                    path_names = [x for x in dir(QLibraryInfo)
                                  if x.endswith('Path')]
                    location = {x: QLibraryInfo.location(
                                getattr(QLibraryInfo, x))
                                for x in path_names}

                # Determine Qt version. Works for Qt 5.8 and later, where
                # QLibraryInfo.version() was introduced.
                try:
                    version = QLibraryInfo.version().segments()
                except AttributeError:
                    version = []
                print(json.dumps({
                    'isDebugBuild': QLibraryInfo.isDebugBuild(),
                    'version': version,
                    'location': location,
                }))
            """ % self.namespace)
            try:
                qli = json.loads(json_str)
            except Exception as e:
                logger.warning('Cannot read QLibraryInfo output: raised %s when '
                               'decoding:\n%s', str(e), json_str)
                qli = {}

            for k, v in qli.items():
                setattr(self, k, v)

            return getattr(self, name)
#-----------------------------------------------------------------------------
# Copyright (c) 2013-2018, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License with exception
# for distributing bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------


from PyInstaller.utils.hooks import exec_statement

# This needed because comtypes wx.lib.activex generates some stuff.
exec_statement("import wx.lib.activex") 
示例#19
0
文件: hook-PyQt5.py 项目: cbgp/diyabc
import os
from pkg_resources import Requirement

from PyInstaller.utils.hooks import qt5_menu_nib_dir, exec_statement
from PyInstaller.compat import getsitepackages, is_darwin, is_win


# On Windows system PATH has to be extended to point to the PyQt5 directory.
# The PySide directory contains Qt dlls. We need to avoid including different
# version of Qt libraries when there is installed another application (e.g. QtCreator)
if is_win:
    from PyInstaller.utils.win32.winutils import extend_system_path
    extend_system_path([os.path.join(x, 'PyQt5') for x in getsitepackages()])


# In the new consolidated mode any PyQt depends on _qt
hiddenimports = ['sip', 'PyQt5.Qt']


# For Qt<5.4 to work on Mac OS X it is necessary to include `qt_menu.nib`.
# This directory contains some resource files necessary to run PyQt or PySide
# app.
qt_version = exec_statement("""
from PyQt5.QtCore import QT_VERSION_STR
print(QT_VERSION_STR)
""")
if is_darwin and qt_version in Requirement.parse("QT<5.4"):
    datas = [
        (qt5_menu_nib_dir(), ''),
    ]
hiddenimports += ["gi.repository.Gio"]

for prog in ['gst-plugins-bad-1.0',
             'gst-plugins-base-1.0',
             'gst-plugins-good-1.0',
             'gst-plugins-ugly-1.0',
             'gstreamer-1.0']:
    datas += collect_glib_translations(prog)

statement = """
import os
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst
Gst.init(None)
reg = Gst.Registry.get()
plug = reg.find_plugin('coreelements')
path = plug.get_filename()
print(os.path.dirname(path))
"""

plugin_path = exec_statement(statement)

# Use a pattern of libgst* since all GStreamer plugins that conform to GStreamer standards start with libgst
# and we may have mixed plugin extensions, e.g., .so and .dylib.
pattern = os.path.join(plugin_path, 'libgst*')

binaries += [(f, os.path.join('gst_plugins')) for f in glob.glob(pattern)]


示例#21
0
from PyInstaller.utils.hooks import exec_statement, collect_submodules

strptime_data_file = exec_statement(
"import inspect; import _strptime; print(inspect.getfile(_strptime))"
)

datas = [ (strptime_data_file, "") ]

hiddenimports = collect_submodules('dateparser')
示例#22
0
#-----------------------------------------------------------------------------
# Copyright (c) 2013, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License with exception
# for distributing bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------


from PyInstaller.utils.hooks import exec_statement

mpl_data_dir = exec_statement(
    "import matplotlib; print matplotlib._get_data_path()")

datas = [
    (mpl_data_dir, ""),
]
示例#23
0
# package directory and this includes:
# - Windows: libenchat-1.dll, libenchat_ispell.dll, libenchant_myspell.dll, other
#            dependent dlls and dictionaries for several languages (de, en, fr)
# - Mac OS X: usually libenchant.dylib and several dictionaries when installed via pip.
binaries = collect_dynamic_libs('enchant')
datas = collect_data_files('enchant')
excludedimports = ['enchant.tests']

# On OS X try to find files from Homebrew or Macports environments.
if is_darwin:
    # Note: env. var. ENCHANT_PREFIX_DIR is implemented only in the development version:
    #    https://github.com/AbiWord/enchant
    #    https://github.com/AbiWord/enchant/pull/2
    # TODO Test this hook with development version of enchant.
    libenchant = exec_statement("""
        from enchant._enchant import e
        print(e._name)
    """).strip()

    installer = get_installer('enchant')
    if installer != 'pip':
        # Note: Name of detected enchant library is 'libenchant.dylib'. However, it
        #       is just symlink to 'libenchant.1.dylib'.
        binaries.append((libenchant, '.'))

        # Collect enchant backends from Macports. Using same file structure as on Windows.
        backends = exec_statement("""
            from enchant import Broker
            for provider in Broker().describe():
                print(provider.file)""").strip().split()
        binaries.extend([(b, 'enchant/lib/enchant') for b in backends])
示例#24
0
# package directory and this includes:
# - Windows: libenchat-1.dll, libenchat_ispell.dll, libenchant_myspell.dll, other
#            dependent dlls and dictionaries for several languages (de, en, fr)
# - Mac OS X: usually libenchant.dylib and several dictionaries when installed via pip.
binaries = collect_dynamic_libs('enchant')
datas = collect_data_files('enchant')


# On OS X try to find files from Homebrew or Macports environments.
if is_darwin:
    # Note: env. var. ENCHANT_PREFIX_DIR is implemented only in the development version:
    #    https://github.com/AbiWord/enchant
    #    https://github.com/AbiWord/enchant/pull/2
    # TODO Test this hook with development version of enchant.
    libenchant = exec_statement("""
from enchant._enchant import e
print(e._name)
""").strip()

    # Check libenchant was not installed via pip but is somewhere on disk.
    # Probably it was installed from Homebrew or Macports.
    if not libenchant.startswith(sys.prefix):
        # 'libenchant' was not installed via pip.
        # Note: Name of detected enchant library is 'libenchant.dylib'. However, it
        #       is just symlink to 'libenchant.1.dylib'.
        binaries.append((libenchant, ''))

        # Collect enchant backends from Macports. Using same file structure as on Windows.
        backends = exec_statement("""
from enchant import Broker
for provider in Broker().describe():
    print(provider.file)""").strip().split()
示例#25
0
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