Compatibility with pyinstaller
This commit is contained in:
@@ -1,78 +0,0 @@
|
|||||||
# This apes hook-matplotlib.backends.py, but REMOVES backends, all but
|
|
||||||
# the ones in the list below.
|
|
||||||
# Courtesy of https://github.com/bpteague/cytoflow/blob/70f9291/packaging/hook-matplotlib.backends.py
|
|
||||||
|
|
||||||
KEEP = ["WXAgg", "WX", "agg"]
|
|
||||||
|
|
||||||
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:
|
|
||||||
if backend_name in KEEP:
|
|
||||||
continue
|
|
||||||
|
|
||||||
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": removed' % backend_name)
|
|
||||||
|
|
||||||
return module_names
|
|
||||||
|
|
||||||
# Freeze all importable backends, as PyInstaller is unable to determine exactly
|
|
||||||
# which backends are required by the current program.
|
|
||||||
e=get_matplotlib_backend_module_names()
|
|
||||||
print(e)
|
|
||||||
excludedimports = e
|
|
||||||
@@ -8,43 +8,25 @@ many upgrade files as there are database versions (version 5 would include
|
|||||||
upgrade files 1-5)
|
upgrade files 1-5)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import pkgutil
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from eos.utils.pyinst_support import iterNamespace
|
||||||
|
|
||||||
updates = {}
|
updates = {}
|
||||||
appVersion = 0
|
appVersion = 0
|
||||||
|
|
||||||
prefix = __name__ + "."
|
prefix = __name__ + "."
|
||||||
|
|
||||||
# load modules to work based with and without pyinstaller
|
for modName in iterNamespace(__name__, __path__):
|
||||||
# from: https://github.com/webcomics/dosage/blob/master/dosagelib/loader.py
|
|
||||||
# see: https://github.com/pyinstaller/pyinstaller/issues/1905
|
|
||||||
|
|
||||||
# load modules using iter_modules()
|
|
||||||
# (should find all filters in normal build, but not pyinstaller)
|
|
||||||
module_names = [m[1] for m in pkgutil.iter_modules(__path__, prefix)]
|
|
||||||
|
|
||||||
# special handling for PyInstaller
|
|
||||||
importers = map(pkgutil.get_importer, __path__)
|
|
||||||
toc = set()
|
|
||||||
for i in importers:
|
|
||||||
if hasattr(i, 'toc'):
|
|
||||||
toc |= i.toc
|
|
||||||
|
|
||||||
for elm in toc:
|
|
||||||
if elm.startswith(prefix):
|
|
||||||
module_names.append(elm)
|
|
||||||
|
|
||||||
for modname in module_names:
|
|
||||||
# loop through python files, extracting update number and function, and
|
# loop through python files, extracting update number and function, and
|
||||||
# adding it to a list
|
# adding it to a list
|
||||||
modname_tail = modname.rsplit('.', 1)[-1]
|
modname_tail = modName.rsplit('.', 1)[-1]
|
||||||
module = __import__(modname, fromlist=True)
|
|
||||||
m = re.match("^upgrade(?P<index>\d+)$", modname_tail)
|
m = re.match("^upgrade(?P<index>\d+)$", modname_tail)
|
||||||
if not m:
|
if not m:
|
||||||
continue
|
continue
|
||||||
index = int(m.group("index"))
|
index = int(m.group("index"))
|
||||||
appVersion = max(appVersion, index)
|
appVersion = max(appVersion, index)
|
||||||
|
module = __import__(modName, fromlist=True)
|
||||||
upgrade = getattr(module, "upgrade", False)
|
upgrade = getattr(module, "upgrade", False)
|
||||||
if upgrade:
|
if upgrade:
|
||||||
updates[index] = upgrade
|
updates[index] = upgrade
|
||||||
|
|||||||
39
eos/utils/pyinst_support.py
Normal file
39
eos/utils/pyinst_support.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
"""
|
||||||
|
Slightly modified version of function taken from here:
|
||||||
|
https://github.com/pyinstaller/pyinstaller/issues/1905#issuecomment-525221546
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import pkgutil
|
||||||
|
|
||||||
|
|
||||||
|
def iterNamespace(name, path):
|
||||||
|
"""Pyinstaller-compatible namespace iteration.
|
||||||
|
|
||||||
|
Yields the name of all modules found at a given Fully-qualified path.
|
||||||
|
|
||||||
|
To have it running with pyinstaller, it requires to ensure a hook inject the
|
||||||
|
"hidden" modules from your plugins folder inside the executable:
|
||||||
|
|
||||||
|
- if your plugins are under the ``myappname/pluginfolder`` module
|
||||||
|
- create a file ``specs/hook-<myappname.pluginfolder>.py``
|
||||||
|
- content of this file should be:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from PyInstaller.utils.hooks import collect_submodules
|
||||||
|
hiddenimports = collect_submodules('<myappname.pluginfolder>')
|
||||||
|
"""
|
||||||
|
prefix = name + "."
|
||||||
|
for p in pkgutil.iter_modules(path, prefix):
|
||||||
|
yield p[1]
|
||||||
|
|
||||||
|
# special handling when the package is bundled with PyInstaller 3.5
|
||||||
|
# See https://github.com/pyinstaller/pyinstaller/issues/1905#issuecomment-445787510
|
||||||
|
toc = set()
|
||||||
|
for importer in pkgutil.iter_importers(name.partition(".")[0]):
|
||||||
|
if hasattr(importer, 'toc'):
|
||||||
|
toc |= importer.toc
|
||||||
|
for name in toc:
|
||||||
|
if name.startswith(prefix):
|
||||||
|
yield name
|
||||||
@@ -7,37 +7,17 @@ item's name. The name of the file is usually arbitrary unless it's used in logic
|
|||||||
elsewhere (in which case can be accessed with packs[name])
|
elsewhere (in which case can be accessed with packs[name])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import pkgutil
|
|
||||||
|
from eos.utils.pyinst_support import iterNamespace
|
||||||
|
|
||||||
|
|
||||||
# init parent dict
|
# init parent dict
|
||||||
all = {}
|
all = {}
|
||||||
|
|
||||||
# init container to store the separate conversion packs in case we need them
|
# init container to store the separate conversion packs in case we need them
|
||||||
packs = {}
|
packs = {}
|
||||||
|
|
||||||
prefix = __name__ + "."
|
for modName in iterNamespace(__name__, __path__):
|
||||||
|
conversionPack = __import__(modName, fromlist="dummy")
|
||||||
# load modules to work based with and without pyinstaller
|
|
||||||
# from: https://github.com/webcomics/dosage/blob/master/dosagelib/loader.py
|
|
||||||
# see: https://github.com/pyinstaller/pyinstaller/issues/1905
|
|
||||||
|
|
||||||
# load modules using iter_modules()
|
|
||||||
# (should find all filters in normal build, but not pyinstaller)
|
|
||||||
module_names = [m[1] for m in pkgutil.iter_modules(__path__, prefix)]
|
|
||||||
|
|
||||||
# special handling for PyInstaller
|
|
||||||
importers = map(pkgutil.get_importer, __path__)
|
|
||||||
toc = set()
|
|
||||||
for i in importers:
|
|
||||||
if hasattr(i, 'toc'):
|
|
||||||
toc |= i.toc
|
|
||||||
|
|
||||||
for elm in toc:
|
|
||||||
if elm.startswith(prefix):
|
|
||||||
module_names.append(elm)
|
|
||||||
|
|
||||||
for modname in module_names:
|
|
||||||
conversionPack = __import__(modname, fromlist="dummy")
|
|
||||||
all.update(conversionPack.CONVERSIONS)
|
all.update(conversionPack.CONVERSIONS)
|
||||||
modname_tail = modname.rsplit('.', 1)[-1]
|
modname_tail = modName.rsplit('.', 1)[-1]
|
||||||
packs[modname_tail] = conversionPack.CONVERSIONS
|
packs[modname_tail] = conversionPack.CONVERSIONS
|
||||||
|
|||||||
Reference in New Issue
Block a user