I’m working on a project where I need to override files located in the ./lib/python3.9/site-packages” directory. I have the following hook that does just that using importlib.util
and sys.meta_path.insert
:
-
The Override files is in
./lib_changes/*
. -
The Hook does work in all of the following files except the
zope+intid.__init__.py
file
import re
import sys
import importlib.util
import os
from Zope2.Startup.serve import main
import logging
LOGGER = logging.getLogger("RunWSGI")
def generate_override_mapping(lib_changes_dir):
override_mapping = {}
for filename in os.listdir(lib_changes_dir):
if filename.endswith(".py"):
module_name = filename[:-3].replace("+", ".")
# Special handling for __init__.py files
if module_name.endswith(".__init__"):
module_name = module_name[:-9]
override_mapping[module_name] = os.path.join(lib_changes_dir, filename)
return override_mapping
class CustomImportHook:
def __init__(self, override_mapping):
self.override_mapping = override_mapping
self.override_counter = 0
def find_spec(self, fullname, path=None, target=None):
if fullname in self.override_mapping:
override_path = self.override_mapping[fullname]
LOGGER.info(f"{fullname} Overide by {override_path}")
self.override_counter += 1
return importlib.util.spec_from_file_location(fullname, override_path)
return None
lib_changes_dir = '/opt/projects/Plone/site/backend/lib_changes'
override_mapping = generate_override_mapping(lib_changes_dir)
sys.meta_path.insert(0, CustomImportHook(override_mapping))
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script.pyw|.exe)?$', '', sys.argv[0])
sys.exit(main())
Problem: I’m trying to override zope.intid.__init__.py
(or any .__init__.py
file) with a custom implementation located in a different directory. However, I’m encountering an issue where the package submodules are not recognized correctly, leading to ModuleNotFoundError errors. For example, once the Hook successfully replaced the implementation of zope.intid.__init__.py
with the one located at ./lib_changes
, improts such as import zope.intid.interfaces
is not longer working (err: ModuleNotFoundError: No module named 'zope.intid.interfaces'; 'zope.intid' is not a package
.
Question: How can I properly override the __init__.py
of the zope.intid package (or any .__init__.py
package file) without breaking the import of its submodules? Is there a way to correctly set up the custom import hook to handle this scenario?