Skip to content

Module watcher imp removal #106

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

Merged
merged 4 commits into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
25 changes: 10 additions & 15 deletions labscript_utils/device_registry/_device_registry.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import importlib.machinery
import os
import importlib
import warnings
Expand All @@ -6,11 +7,6 @@
from labscript_utils import dedent
from labscript_utils.labconfig import LabConfig

# deal with removal of imp from python 3.12
try:
import _imp as imp
except ImportError:
import imp

"""This file contains the machinery for registering and looking up what BLACS tab and
runviewer parser classes belong to a particular labscript device. "labscript device"
Expand Down Expand Up @@ -253,20 +249,19 @@ def register_classes(labscript_device_name, BLACS_tab=None, runviewer_parser=Non

def populate_registry():
"""Walk the labscript_devices folder looking for files called register_classes.py,
and run them (i.e. import them). These files are expected to make calls to
and run them. These files are expected to make calls to
register_classes() to inform us of what BLACS tabs and runviewer classes correspond
to their labscript device classes."""
# We import the register_classes modules as a direct submodule of labscript_devices.
# But they cannot all have the same name, so we import them as
# labscript_devices._register_classes_script_<num> with increasing number.
module_num = 0
# We execute the register_classes modules as a direct submodule of labscript_devices.
for devices_dir in LABSCRIPT_DEVICES_DIRS:
for folder, _, filenames in os.walk(devices_dir):
if 'register_classes.py' in filenames:
# The module name is the path to the file, relative to the labscript suite
# install directory:
# Open the file using the import machinery, and import it as module_name.
fp, pathname, desc = imp.find_module('register_classes', [folder])
module_name = 'labscript_devices._register_classes_%d' % module_num
_ = imp.load_module(module_name, fp, pathname, desc)
module_num += 1
# Open the file using the import machinery, and run it
spec = importlib.machinery.PathFinder.find_spec('register_classes', [folder])
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
# fully importing module would require adding to sys.modules
# and each import would need to have unique names
# but we just need to run the registering code, not actually import the module
47 changes: 31 additions & 16 deletions labscript_utils/modulewatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@
import site
import sysconfig

# deal with removal of imp from python 3.12
try:
import _imp as imp
except ImportError:
import imp


# Directories in which the standard library and installed packages may be located.
# Modules in these locations will be whitelisted:
Expand Down Expand Up @@ -63,16 +57,8 @@ def mainloop(self):
while True:
time.sleep(1)
with self.lock:
# Acquire the import lock so that we don't unload modules whilst an
# import is in progess:
imp.acquire_lock()
try:
if self.check():
self.unload()
finally:
# We're done mucking around with the cached modules, normal imports
# in other threads may resume:
imp.release_lock()
if self.check():
self.unload()

def check(self):
unload_required = False
Expand Down Expand Up @@ -138,3 +124,32 @@ def unload(self):
# code holds references to sys.meta_path, and to preserve order, since order
# is relevant.
sys.meta_path[:] = self.meta_whitelist

if __name__ == "__main__":

from pathlib import Path
import time

dict1 = {'t': 5, 'val': 10}
dict2 = {'t': 5, 'val': 11}

print('ModuleWatcher instatiated in debug mode')
module_watcher = ModuleWatcher(debug=True)

# import a local module
import labscript_utils.dict_diff
print('imported labscript_utils.dict_diff')
print(labscript_utils.dict_diff.dict_diff(dict1, dict2))
print('used dict_diff function, waiting 2 seconds for module watcher to update')
time.sleep(2)

# now pretend it has been updated
ex_mod = Path('dict_diff.py')
ex_mod.touch()
print('dict_diff module touched, waiting 2 seconds for ModuleWatcher to notice')
time.sleep(2)

print(labscript_utils.dict_diff.dict_diff(dict1, dict2))
print('Used dict_diff again, waiting 2 seconds for ModuleWatcher to not do anything')
time.sleep(2)