Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated matplotlib hook to handle matplotlib.libs direcory (added in … #182

Merged
merged 2 commits into from
Oct 7, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Updated matplotlib hook to handle matplotlib.libs direcory (added in …
…mpl >= 3.7.0

Added a hook for mpl_toolkits for the same reason.
  • Loading branch information
mike committed Apr 19, 2023
commit f83e16e652953e53b7e102af5ffaf7bf6a74257b
116 changes: 109 additions & 7 deletions py2exe/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,10 @@ def hook_infi(finder, module):
def hook_matplotlib(finder, module):
"""matplotlib requires data files in a 'mpl-data' subdirectory in
the same directory as the executable.

Also, matplotlib >= 3.7.0 moved .dlls to a matplotlib.libs directory,
requiring that we override the '_delvewheel_init_patch_1_3_3' function
so that those .dlls can be found in the same directory as the executable.
"""
import ast
from pkg_resources._vendor.packaging import version as pkgversion
Expand All @@ -397,20 +401,80 @@ def hook_matplotlib(finder, module):
# matplotlib <=3.3.4 requires '_get_data_path' to be patched
# matplotlib >= 3.4.0 requires 'get_data_path' to be patched
mpl_version = pkgversion.parse(matplotlib.__version__)
node_to_be_patched = 'get_data_path' if mpl_version >= pkgversion.parse('3.4.0') else '_get_data_path'
get_data_node_to_be_patched = 'get_data_path' if mpl_version >= pkgversion.parse('3.4.0') else '_get_data_path'

# matplotlib >= 3.7.0 requires patching '_delvewheel_init_patch_1_3_3'
if mpl_version >= pkgversion.parse('3.7.0'):

tree = ast.parse(module.__source__)
devel_node_to_be_patched = '_delvewheel_init_patch_1_3_3'
zobac marked this conversation as resolved.
Show resolved Hide resolved

mpl_libs_path = os.path.abspath(os.path.join(os.path.dirname(matplotlib.__file__), os.pardir, 'matplotlib.libs'))
if os.path.isdir(mpl_libs_path):
from os import listdir
zobac marked this conversation as resolved.
Show resolved Hide resolved
dlls = [os.path.join(mpl_libs_path, fln)
for fln in listdir(mpl_libs_path)
if fln.endswith('.dll')]
for dll in dlls:
finder.add_dll(dll)

class ChangeDef(ast.NodeTransformer):
def visit_FunctionDef(self, node: ast.FunctionDef):
if devel_node_to_be_patched in node.name:
node.body = ast.parse('pass').body
elif get_data_node_to_be_patched in node.name:
node.body = ast.parse('return os.path.join(os.path.dirname(sys.executable), "mpl-data")').body
return node

else:

class ChangeDef(ast.NodeTransformer):
def visit_FunctionDef(self, node: ast.FunctionDef):
if get_data_node_to_be_patched in node.name:
node.body = ast.parse('return os.path.join(os.path.dirname(sys.executable), "mpl-data")').body
return node

finder.import_hook("mpl_toolkits")

class ChangeDef(ast.NodeTransformer):
def visit_FunctionDef(self, node: ast.FunctionDef):
if node.name == node_to_be_patched:
node.body = ast.parse('return os.path.join(os.path.dirname(sys.executable), "mpl-data")').body
return node

t = ChangeDef()
patched_tree = t.visit(tree)

module.__code_object__ = compile(patched_tree, module.__file__, "exec", optimize=module.__optimize__)

finder.import_hook("mpl_toolkits")

def hook_mpl_toolkits(finder, module):
"""matplotlib >= 3.7.0 moved .dlls to a matplotlib.libs directory,
requiring that we override the '_delvewheel_init_patch_1_3_3' function
in mpl_tollkits so that those .dlls can be found in the same directory
as the executable.
"""
import ast
from pkg_resources._vendor.packaging import version as pkgversion

import matplotlib
mpl_version = pkgversion.parse(matplotlib.__version__)

if mpl_version >= pkgversion.parse('3.7.0'):

import mpl_toolkits

tree = ast.parse(module.__source__)
devel_node_to_be_patched = '_delvewheel_init_patch_1_3_3'

class ChangeDef(ast.NodeTransformer):
def visit_FunctionDef(self, node: ast.FunctionDef):
if devel_node_to_be_patched in node.name:
node.body = ast.parse('pass').body
return node

t = ChangeDef()
patched_tree = t.visit(tree)

module.__code_object__ = compile(patched_tree, module.__file__, "exec", optimize=module.__optimize__)

else:
zobac marked this conversation as resolved.
Show resolved Hide resolved
finder.import_hook("mpl_toolkits")

def hook_numpy(finder, module):
"""numpy for Python 3 still tries to import some Python 2 modules;
Expand Down Expand Up @@ -805,3 +869,41 @@ def hook_wx(finder, module):
when importing the full wx package
"""
finder.excludes.append("wx.lib.pubsub")


def hook_zmq(finder, module):
"""pyzmq >= 3.7.0 moved .dlls to a matplotlib.libs directory,
zobac marked this conversation as resolved.
Show resolved Hide resolved
requiring that we override the '_delvewheel_init_patch_1_3_3' function
in mpl_tollkits so that those .dlls can be found in the same directory
as the executable.
"""
import ast
from pkg_resources._vendor.packaging import version as pkgversion

import zmq
zmq_version = pkgversion.parse(zmq.__version__)

if zmq_version >= pkgversion.parse('23.0.0'):
zobac marked this conversation as resolved.
Show resolved Hide resolved

tree = ast.parse(module.__source__)
devel_node_to_be_patched = '_delvewheel_init_patch_0_0_22'

class ChangeDef(ast.NodeTransformer):
def visit_FunctionDef(self, node: ast.FunctionDef):
if devel_node_to_be_patched in node.name:
node.body = ast.parse('pass').body
return node

t = ChangeDef()
patched_tree = t.visit(tree)

module.__code_object__ = compile(patched_tree, module.__file__, "exec", optimize=module.__optimize__)

zmp_libs_path = os.path.abspath(os.path.join(os.path.dirname(zmq.__file__), os.pardir, 'pyzmq.libs'))
if os.path.isdir(zmp_libs_path):
from os import listdir
dlls = [os.path.join(zmp_libs_path, fln)
for fln in listdir(zmp_libs_path)
if fln.endswith('.dll')]
for dll in dlls:
finder.add_dll(dll)
zobac marked this conversation as resolved.
Show resolved Hide resolved