From 21daf2e0f0a99bfab9339143339fa0de992cf38e Mon Sep 17 00:00:00 2001 From: Chris Billington Date: Fri, 9 Mar 2018 11:16:22 +1100 Subject: [PATCH 1/6] filepath_fix: Don't use __file__ to infer the location of the script - it is unreliable due to relative paths and the possibility of someone having called os.chdir() --- __init__.py | 5 +++++ __main__.py | 6 +++--- analysis_submission.py | 4 +++- compile_and_restart.py | 5 ++++- device_base_class.py | 9 +++++---- notifications.py | 7 ++++--- plugins/__init__.py | 7 ++++--- plugins/connection_table/__init__.py | 5 +++-- plugins/delete_repeated_shots/__init__.py | 3 ++- plugins/general/__init__.py | 5 +++-- plugins/theme/__init__.py | 4 +++- tab_base_classes.py | 5 +++-- 12 files changed, 42 insertions(+), 23 deletions(-) diff --git a/__init__.py b/__init__.py index f4afbb3d..dd00a94b 100644 --- a/__init__.py +++ b/__init__.py @@ -12,3 +12,8 @@ ##################################################################### __version__ = '2.2.0' + + +import os +from labscript_utils import labscript_suite_install_dir +BLACS_DIR = os.path.join(labscript_suite_install_dir, 'blacs') \ No newline at end of file diff --git a/__main__.py b/__main__.py index e3e5ea7f..745dfed9 100644 --- a/__main__.py +++ b/__main__.py @@ -147,7 +147,7 @@ #import settings_pages import blacs.plugins as plugins -os.chdir(os.path.abspath(os.path.dirname(__file__))) +from blacs import BLACS_DIR def set_win_appusermodel(window_id): @@ -156,7 +156,7 @@ def set_win_appusermodel(window_id): executable = sys.executable.lower() if not executable.endswith('w.exe'): executable = executable.replace('.exe', 'w.exe') - relaunch_command = executable + ' ' + os.path.abspath(__file__.replace('.pyc', '.py')) + relaunch_command = executable + ' ' + os.path.join(BLACS_DIR, '__main__.py') relaunch_display_name = app_descriptions['blacs'] set_appusermodel(window_id, appids['blacs'], icon_path, relaunch_command, relaunch_display_name) @@ -222,7 +222,7 @@ def __init__(self,application): loader = UiLoader() loader.registerCustomWidget(QueueTreeview) #loader.registerCustomPromotion('BLACS',BLACSWindow) - self.ui = loader.load(os.path.join(os.path.dirname(os.path.realpath(__file__)),'main.ui'), BLACSWindow()) + self.ui = loader.load(os.path.join(BLACS_DIR, 'main.ui'), BLACSWindow()) logger.info('BLACS ui loaded') self.ui.blacs=self self.tab_widgets = {} diff --git a/analysis_submission.py b/analysis_submission.py index eeb4a00d..1fb74f5f 100644 --- a/analysis_submission.py +++ b/analysis_submission.py @@ -27,6 +27,8 @@ from socket import gaierror import labscript_utils.shared_drive from labscript_utils.qtwidgets.elide_label import elide_label +from blacs import BLACS_DIR + class AnalysisSubmission(object): def __init__(self, BLACS, blacs_ui): @@ -34,7 +36,7 @@ def __init__(self, BLACS, blacs_ui): self.BLACS = BLACS self.port = int(self.BLACS.exp_config.get('ports', 'lyse')) - self._ui = UiLoader().load(os.path.join(os.path.dirname(os.path.realpath(__file__)),'analysis_submission.ui')) + self._ui = UiLoader().load(os.path.join(BLACS_DIR, 'analysis_submission.ui')) blacs_ui.analysis.addWidget(self._ui) self._ui.frame.setMinimumWidth(blacs_ui.queue_controls_frame.sizeHint().width()) elide_label(self._ui.resend_shots_label, self._ui.failed_to_send_frame.layout(), Qt.ElideRight) diff --git a/compile_and_restart.py b/compile_and_restart.py index 9987f898..7c69b873 100644 --- a/compile_and_restart.py +++ b/compile_and_restart.py @@ -21,6 +21,9 @@ import runmanager from qtutils.outputbox import OutputBox +from blacs import BLACS_DIR + + class CompileAndRestart(QDialog): def __init__(self, blacs, globals_files,connection_table_labscript, output_path, close_notification_func=None): QDialog.__init__(self,blacs['ui']) @@ -33,7 +36,7 @@ def __init__(self, blacs, globals_files,connection_table_labscript, output_path, self.blacs = blacs self.close_notification_func = close_notification_func - self.ui = UiLoader().load(os.path.join(os.path.dirname(os.path.realpath(__file__)),'compile_and_restart.ui')) + self.ui = UiLoader().load(os.path.join(BLACS_DIR, 'compile_and_restart.ui')) self.output_box = OutputBox(self.ui.verticalLayout) self.ui.restart.setEnabled(False) diff --git a/device_base_class.py b/device_base_class.py index 8e5ca10a..c5490ea7 100644 --- a/device_base_class.py +++ b/device_base_class.py @@ -23,6 +23,7 @@ import labscript_utils.excepthook from qtutils import UiLoader +from blacs import BLACS_DIR from blacs.tab_base_classes import Tab, Worker, define_state from blacs.tab_base_classes import MODE_MANUAL, MODE_TRANSITION_TO_BUFFERED, MODE_TRANSITION_TO_MANUAL, MODE_BUFFERED from blacs.output_classes import AO, DO, DDS @@ -445,7 +446,7 @@ def check_remote_values(self): changed = True if changed: - ui = UiLoader().load(os.path.join(os.path.dirname(os.path.realpath(__file__)),'tab_value_changed_dds.ui')) + ui = UiLoader().load(os.path.join(BLACS_DIR, 'tab_value_changed_dds.ui')) ui.channel_label.setText(self._DDS[channel].name) for sub_chnl in front_value: ui.__getattribute__('front_%s_value'%sub_chnl).setText(front_values_formatted[sub_chnl]) @@ -464,7 +465,7 @@ def check_remote_values(self): remote_value = str(bool(int(remote_value))) if front_value != remote_value: changed = True - ui = UiLoader().load(os.path.join(os.path.dirname(os.path.realpath(__file__)),'tab_value_changed.ui')) + ui = UiLoader().load(os.path.join(BLACS_DIR, 'tab_value_changed.ui')) ui.channel_label.setText(self._DO[channel].name) ui.front_value.setText(front_value) ui.remote_value.setText(remote_value) @@ -474,7 +475,7 @@ def check_remote_values(self): remote_value = ("%."+str(self._AO[channel]._decimals)+"f")%remote_value if front_value != remote_value: changed = True - ui = UiLoader().load(os.path.join(os.path.dirname(os.path.realpath(__file__)),'tab_value_changed.ui')) + ui = UiLoader().load(os.path.join(BLACS_DIR, 'tab_value_changed.ui')) ui.channel_label.setText(self._AO[channel].name) ui.front_value.setText(front_value) ui.remote_value.setText(remote_value) @@ -703,7 +704,7 @@ def transition_to_manual(self): import logging.handlers # Setup logging: logger = logging.getLogger('BLACS') - handler = logging.handlers.RotatingFileHandler('BLACS.log', maxBytes=1024**2, backupCount=0) + handler = logging.handlers.RotatingFileHandler(os.path.join(BLACS_DIR, 'BLACS.log'), maxBytes=1024**2, backupCount=0) formatter = logging.Formatter('%(asctime)s %(levelname)s %(name)s: %(message)s') handler.setFormatter(formatter) handler.setLevel(logging.DEBUG) diff --git a/notifications.py b/notifications.py index 3960b0c4..0f252868 100644 --- a/notifications.py +++ b/notifications.py @@ -15,6 +15,7 @@ import os from qtutils import UiLoader +from blacs import BLACS_DIR logger = logging.getLogger('BLACS.NotificationManager') @@ -50,7 +51,7 @@ def add_notification(self, notification_class): get_state = lambda: self.get_state(notification_class) # create layout/widget with appropriate buttons and the widget from the notification class - ui = UiLoader().load(os.path.join(os.path.dirname(os.path.realpath(__file__)),'notification_widget.ui')) + ui = UiLoader().load(os.path.join(BLACS_DIR, 'notification_widget.ui')) ui.hide_button.setVisible(bool(properties['can_hide'])) ui.hide_button.clicked.connect(lambda: hide_func(True)) ui.close_button.setVisible(bool(properties['can_close'])) @@ -76,7 +77,7 @@ def add_notification(self, notification_class): #TODO: Make the minimized widget - ui2 = UiLoader().load(os.path.join(os.path.dirname(os.path.realpath(__file__)),'notification_minimized_widget.ui')) + ui2 = UiLoader().load(os.path.join(BLACS_DIR, 'notification_minimized_widget.ui')) #ui2.hide() if not hasattr(self._notifications[notification_class], 'name'): self._notifications[notification_class].name = notification_class.__name__ @@ -153,4 +154,4 @@ def close_all(self): notification.close() except: pass - \ No newline at end of file + diff --git a/plugins/__init__.py b/plugins/__init__.py index 0b605bcd..61f18737 100644 --- a/plugins/__init__.py +++ b/plugins/__init__.py @@ -16,6 +16,8 @@ import logging import importlib from labscript_utils.labconfig import LabConfig +from blacs import BLACS_DIR +PLUGINS_DIR = os.path.join(BLACS_DIR, 'plugins') default_plugins = ['connection_table', 'general', 'memory', 'theme'] @@ -26,9 +28,8 @@ exp_config.add_section('BLACS/plugins') modules = {} -this_dir = os.path.dirname(os.path.abspath(__file__)) -for module_name in os.listdir(this_dir): - if os.path.isdir(os.path.join(this_dir, module_name)): +for module_name in os.listdir(PLUGINS_DIR): + if os.path.isdir(os.path.join(PLUGINS_DIR, module_name)): # is it a new plugin? # If so lets add it to the config if not module_name in [name for name, val in exp_config.items('BLACS/plugins')]: diff --git a/plugins/connection_table/__init__.py b/plugins/connection_table/__init__.py index fc41c089..a378492b 100644 --- a/plugins/connection_table/__init__.py +++ b/plugins/connection_table/__init__.py @@ -23,6 +23,7 @@ from blacs.compile_and_restart import CompileAndRestart from labscript_utils.filewatcher import FileWatcher from qtutils import * +from blacs.plugins import PLUGINS_DIR FILEPATH_COLUMN = 0 name = "Connection Table" @@ -128,7 +129,7 @@ def __init__(self, BLACS): self.filewatcher = None # Create the widget - self._ui = UiLoader().load(os.path.join(os.path.dirname(os.path.realpath(__file__)),'notification.ui')) + self._ui = UiLoader().load(os.path.join(PLUGINS_DIR, module, 'notification.ui')) self._ui.button.clicked.connect(self.on_recompile_connection_table) #self._ui.hide() @@ -198,7 +199,7 @@ def __init__(self,data): # Create the page, return the page and an icon to use on the label (the class name attribute will be used for the label text) def create_dialog(self,notebook): - ui = UiLoader().load(os.path.join(os.path.dirname(os.path.realpath(__file__)),'connection_table.ui')) + ui = UiLoader().load(os.path.join(PLUGINS_DIR, module, 'connection_table.ui')) # Create the models, get the views, and link them!! self.models = {} diff --git a/plugins/delete_repeated_shots/__init__.py b/plugins/delete_repeated_shots/__init__.py index 706ac267..3ea6b890 100644 --- a/plugins/delete_repeated_shots/__init__.py +++ b/plugins/delete_repeated_shots/__init__.py @@ -22,6 +22,7 @@ from labscript_utils.shared_drive import path_to_agnostic import zprocess.locking +from blacs.plugins import PLUGINS_DIR name = "Delete repeated shots" module = "delete_repeated_shots" # should be folder name @@ -49,7 +50,7 @@ def plugin_setup_complete(self, BLACS): self.BLACS = BLACS # Add our controls to the BLACS UI: - self.ui = UiLoader().load(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'controls.ui')) + self.ui = UiLoader().load(os.path.join(PLUGINS_DIR, module, 'controls.ui')) BLACS['ui'].queue_controls_frame.layout().addWidget(self.ui) # Restore settings to the GUI controls: diff --git a/plugins/general/__init__.py b/plugins/general/__init__.py index ec57b954..ef4385df 100644 --- a/plugins/general/__init__.py +++ b/plugins/general/__init__.py @@ -14,7 +14,8 @@ import os from qtutils import UiLoader - +from blacs.plugins import PLUGINS_DIR + class Plugin(object): def __init__(self, initial_settings): self.menu = None @@ -69,7 +70,7 @@ def __init__(self,data): # Create the GTK page, return the page and an icon to use on the label (the class name attribute will be used for the label text) def create_dialog(self,notebook): - ui = UiLoader().load(os.path.join(os.path.dirname(os.path.realpath(__file__)),'general.ui')) + ui = UiLoader().load(os.path.join(PLUGINS_DIR, 'general', 'general.ui')) # get the widgets! self.widgets = {} diff --git a/plugins/theme/__init__.py b/plugins/theme/__init__.py index 35a8baf8..32bd21b1 100644 --- a/plugins/theme/__init__.py +++ b/plugins/theme/__init__.py @@ -16,6 +16,8 @@ from qtutils import * +from blacs.plugins import PLUGINS_DIR + name = "GUI Theme" module = "theme" # should be folder name logger = logging.getLogger('BLACS.plugin.%s'%module) @@ -169,7 +171,7 @@ def on_set_green_button_theme(self): # Create the page, return the page and an icon to use on the label (the class name attribute will be used for the label text) def create_dialog(self,notebook): - ui = UiLoader().load(os.path.join(os.path.dirname(os.path.realpath(__file__)),'theme.ui')) + ui = UiLoader().load(PLUGINS_DIR, module, 'theme.ui') # restore current stylesheet ui.stylesheet_text.setPlainText(self.data['stylesheet']) diff --git a/tab_base_classes.py b/tab_base_classes.py index 6288a9b0..7fc8823a 100644 --- a/tab_base_classes.py +++ b/tab_base_classes.py @@ -34,6 +34,7 @@ import qtutils.icons from labscript_utils.qtwidgets.elide_label import elide_label +from blacs import BLACS_DIR class Counter(object): """A class with a single method that @@ -246,7 +247,7 @@ def __init__(self,notebook,settings,restart=False): self._restart_receiver = [] # Load the UI - self._ui = UiLoader().load(os.path.join(os.path.dirname(os.path.realpath(__file__)),'tab_frame.ui')) + self._ui = UiLoader().load(os.path.join(BLACS_DIR, 'tab_frame.ui')) self._layout = self._ui.device_layout self._device_widget = self._ui.device_controls self._changed_widget = self._ui.changed_widget @@ -992,7 +993,7 @@ def baz(self,zzz,*args,**kwargs): import logging.handlers # Setup logging: logger = logging.getLogger('BLACS') - handler = logging.handlers.RotatingFileHandler('BLACS.log', maxBytes=1024**2, backupCount=0) + handler = logging.handlers.RotatingFileHandler(os.path.join(BLACS_DIR, 'BLACS.log'), maxBytes=1024**2, backupCount=0) formatter = logging.Formatter('%(asctime)s %(levelname)s %(name)s: %(message)s') handler.setFormatter(formatter) handler.setLevel(logging.DEBUG) From 2b765c0f83b1c98aad29c7f83f19c9905e35daf4 Mon Sep 17 00:00:00 2001 From: Chris Billington Date: Mon, 12 Mar 2018 20:06:56 +1100 Subject: [PATCH 2/6] Backed out changeset: 2540cf1114c6 --- __main__.py | 10 +++++----- device_base_class.py | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/__main__.py b/__main__.py index 7b84d224..e3e5ea7f 100644 --- a/__main__.py +++ b/__main__.py @@ -133,19 +133,19 @@ # And for icons: import qtutils.icons # Analysis Submission code -from analysis_submission import AnalysisSubmission +from blacs.analysis_submission import AnalysisSubmission # Queue Manager Code -from experiment_queue import QueueManager, QueueTreeview +from blacs.experiment_queue import QueueManager, QueueTreeview # Module containing hardware compatibility: import labscript_devices # Save/restore frontpanel code -from front_panel_settings import FrontPanelSettings +from blacs.front_panel_settings import FrontPanelSettings # Notifications system -from notifications import Notifications +from blacs.notifications import Notifications # Preferences system from labscript_utils.settings import Settings #import settings_pages -import plugins +import blacs.plugins as plugins os.chdir(os.path.abspath(os.path.dirname(__file__))) diff --git a/device_base_class.py b/device_base_class.py index 611c7b8f..8e5ca10a 100644 --- a/device_base_class.py +++ b/device_base_class.py @@ -23,9 +23,9 @@ import labscript_utils.excepthook from qtutils import UiLoader -from tab_base_classes import Tab, Worker, define_state -from tab_base_classes import MODE_MANUAL, MODE_TRANSITION_TO_BUFFERED, MODE_TRANSITION_TO_MANUAL, MODE_BUFFERED -from output_classes import AO, DO, DDS +from blacs.tab_base_classes import Tab, Worker, define_state +from blacs.tab_base_classes import MODE_MANUAL, MODE_TRANSITION_TO_BUFFERED, MODE_TRANSITION_TO_MANUAL, MODE_BUFFERED +from blacs.output_classes import AO, DO, DDS from labscript_utils.qtwidgets.toolpalette import ToolPaletteGroup From 5354b907be91a2da559aa411023c82db8ec0e93c Mon Sep 17 00:00:00 2001 From: Chris Billington Date: Mon, 12 Mar 2018 20:22:17 +1100 Subject: [PATCH 3/6] filepath_fix: Re-added absolute imports, plus the missing ones that caused issue #36. --- __init__.py | 10 +++++++++- __main__.py | 2 +- experiment_queue.py | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/__init__.py b/__init__.py index dd00a94b..bfb76bc8 100644 --- a/__init__.py +++ b/__init__.py @@ -16,4 +16,12 @@ import os from labscript_utils import labscript_suite_install_dir -BLACS_DIR = os.path.join(labscript_suite_install_dir, 'blacs') \ No newline at end of file +if labscript_suite_install_dir is not None: + BLACS_DIR = os.path.join(labscript_suite_install_dir, 'blacs') +else: + # No labscript install directory found? Fall back to relying on __file__ and + # hope that it is not a relative path that has been invalidated by a call to + # os.chdir() between interpreter start and now (this can happen if blacs is run + # with python 2 using "python -m blacs" whilst the current directory is the + # parent of the blacs directory): + BLACS_DIR = os.path.dirname(os.path.realpath(__file__)) diff --git a/__main__.py b/__main__.py index 745dfed9..136710ed 100644 --- a/__main__.py +++ b/__main__.py @@ -123,7 +123,7 @@ # Connection Table Code -from connections import ConnectionTable +from blacs.connections import ConnectionTable #Draggable Tab Widget Code from labscript_utils.qtwidgets.dragdroptab import DragDropTabWidget # Lab config code diff --git a/experiment_queue.py b/experiment_queue.py index 234e404e..a7e7aded 100644 --- a/experiment_queue.py +++ b/experiment_queue.py @@ -32,7 +32,7 @@ from labscript_utils.qtwidgets.elide_label import elide_label # Connection Table Code -from connections import ConnectionTable +from blacs.connections import ConnectionTable from blacs.tab_base_classes import MODE_MANUAL, MODE_TRANSITION_TO_BUFFERED, MODE_TRANSITION_TO_MANUAL, MODE_BUFFERED FILEPATH_COLUMN = 0 From 727fa24c76f039f6ef2ebb5cb53eb42301867986 Mon Sep 17 00:00:00 2001 From: Chris Billington Date: Mon, 12 Mar 2018 20:29:04 +1100 Subject: [PATCH 4/6] filepath_fix: Missed one os.path.join() --- plugins/theme/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/theme/__init__.py b/plugins/theme/__init__.py index 32bd21b1..e3aa6a33 100644 --- a/plugins/theme/__init__.py +++ b/plugins/theme/__init__.py @@ -171,7 +171,7 @@ def on_set_green_button_theme(self): # Create the page, return the page and an icon to use on the label (the class name attribute will be used for the label text) def create_dialog(self,notebook): - ui = UiLoader().load(PLUGINS_DIR, module, 'theme.ui') + ui = UiLoader().load(os.path.join(PLUGINS_DIR, module, 'theme.ui')) # restore current stylesheet ui.stylesheet_text.setPlainText(self.data['stylesheet']) From e91647d629411816f0689faaca0c8cfbcadbe870 Mon Sep 17 00:00:00 2001 From: Chris Billington Date: Mon, 12 Mar 2018 20:36:17 +1100 Subject: [PATCH 5/6] filepath_fix: Error if we still cannot find BLACS directory --- __init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/__init__.py b/__init__.py index bfb76bc8..968564bc 100644 --- a/__init__.py +++ b/__init__.py @@ -25,3 +25,7 @@ # with python 2 using "python -m blacs" whilst the current directory is the # parent of the blacs directory): BLACS_DIR = os.path.dirname(os.path.realpath(__file__)) +if not os.path.isdir(BLACS_DIR): + # Don't want to continue if we have not found the directory: + msg = "Cannot locate the directory BLACS is installed in." + raise RuntimeError(msg) From fec45a36ddf9fa63aba2c0ae413e357788fed35e Mon Sep 17 00:00:00 2001 From: Chris Billington Date: Mon, 12 Mar 2018 23:21:43 +0000 Subject: [PATCH 6/6] filepath_fix: Close branch filepath_fix