Updated matplotlib hook to handle matplotlib.libs direcory (added in …#182
Conversation
…mpl >= 3.7.0 Added a hook for mpl_toolkits for the same reason.
albertosottile
left a comment
There was a problem hiding this comment.
Thank you for this contribution! I just have a few minor change requests.
|
How about if add special functions to handle packages distributed by delvewheel? class TheFinderClass:
def add_dlls(self, path, suffixes=(".dll", ".pyd")):
path = os.path.realpath(path)
if os.path.isdir(path):
dlls = [os.path.join(path, fn)
for fn in os.listdir(path)
if fn.endswith(suffixes)]
for dll in dlls:
self.add_dll(dll)
def hook_delvewheel_dist(finder, module, need_ast=False):
"""Patches which distributed by delvewheel are not needed, here remove them
and move all the .dll files to the root of sys.executable.
If need_ast is False, module.__code_object__ will be replaced, return None.
If need_ast is True, return the AST object for post-use, don't forget
replace the code at the end.
"""
import ast
# we don't need ast.NodeTransformer to replace the whole subnode
class NodeVisitor(ast.NodeVisitor):
filter_assign = False
filter_constant = False
def visit_FunctionDef(self, node: ast.FunctionDef):
if not node.name.startswith("_delvewheel_init_patch_"):
return
try:
self.filter_assign = True
self.generic_visit(node)
except UserWarning:
pass
else:
import warnings
warnings.warn(f"{node.name} be matched, but no libs name be found",
RuntimeWarning, 3)
finally:
node.body = ast.parse("pass").body
# all done, early cancel
raise UserWarning
def visit_Assign(self, node: ast.Assign):
if not self.filter_assign:
return
target = node.targets[0]
if isinstance(target, ast.Name) and target.id == "libs_dir":
self.filter_constant = True
self.generic_visit(node)
self.filter_constant = False
def visit_Constant(self, node: ast.Constant):
self.add_dlls(node.value)
if hasattr(ast, "Str")
# py37 and below
def visit_Str(self, node: ast.Str):
self.add_dlls(node.s)
def add_dlls(self, name):
if self.filter_constant and isinstance(name, str):
finder.add_dlls(finder, os.path.join(
os.path.dirname(module.__file__), os.pardir, name))
# done, raise a signal
raise UserWarning
tree = ast.parse(module.__source__)
try:
NodeVisitor().visit(tree)
except UserWarning:
pass
if need_ast:
return tree
module.__code_object__ = compile(
tree, module.__file__, "exec", optimize=module.__optimize__) |
…ndle locale-data .dat files
|
Ultimately, I think @SeaHOH is onto a better solution, but I didn't know where to put/instanciate TheFinderClass so I left it out for now. |
It imply |
|
@SeaHOH Would you like to submit a PR with your solution? |
|
I tried to run this branch on Actions and now it fails on @SeaHOH Let me know if you want to prepare a PR, otherwise I can implement this feature based on the code that you provided up here and credit you in a comment. What is not entirely clear to me is how to hook this general purpose code in the specific hooks (e.g. |
I'd like to do, but actually will not, I have no time to test a lot of packages.
Yes, I think so, just a call, all works can be done in the function. |
…mpl >= 3.7.0
Added a hook for mpl_toolkits for the same reason.
Not sure if I handled mpl_toolkits < 3.7.0 properly (or if it needs to be handled for those versions)