Ejemplo n.º 1
0
    def doInit(self, mode):
        # import server and serializer class
        servercls = importString(self.servercls)
        serialcls = importString(self.serializercls)

        self._stoprequest = False
        # the controller represents the internal script execution machinery
        if self.autosimulate and not config.sandbox_simulation:
            raise ConfigurationError('autosimulation configured but sandbox'
                                     ' deactivated')

        self._controller = ExecutionController(self.log, self.emit_event,
                                               'startup', self.simmode,
                                               self.autosimulate)

        # cache log messages emitted so far
        self._messages = []

        host, port = parseHostPort(self.server, DEFAULT_PORT)

        # create server (transport + serializer)
        self._server = servercls(self, (host, port), serialcls())

        self._watch_worker = createThread('daemon watch monitor',
                                          self._watch_entry)
Ejemplo n.º 2
0
 def initDataReaders(self):
     try:
         # just import to register all default readers
         # pylint: disable=unused-import
         import nicos.devices.datasinks
     except ImportError:
         pass
     classes = self.gui_conf.options.get('reader_classes', [])
     for clsname in classes:
         try:
             importString(clsname)
         except ImportError:
             pass
Ejemplo n.º 3
0
def createPanel(item, window, menuwindow, topwindow, log):
    try:
        cls = importString(item.clsname)
    except Exception:
        log.exception('Could not import class %s to create panel',
                      item.clsname)
        return None
    log.debug('creating panel: %s', item.clsname)
    p = cls(menuwindow, window.client, item.options or {})
    window.addPanel(p)
    topwindow.addPanel(p, False)

    for toolbar in p.getToolbars():
        # this helps for serializing window state
        toolbar.setObjectName(toolbar.windowTitle())
        if hasattr(menuwindow, 'toolBarWindows'):
            menuwindow.insertToolBar(menuwindow.toolBarWindows, toolbar)
        else:
            menuwindow.addToolBar(toolbar)
        toolbar.setVisible(False)
    for menu in p.getMenus():
        if hasattr(menuwindow, 'menuWindows'):
            p.actions.update((menuwindow.menuBar().insertMenu(
                menuwindow.menuWindows.menuAction(), menu), ))
        else:
            p.actions.update((menuwindow.menuBar().addMenu(menu), ))

    p.setCustomStyle(window.user_font, window.user_color)
    if window.client.isconnected and hasattr(p, 'on_client_connected'):
        p.on_client_connected()
    return p
Ejemplo n.º 4
0
 def check_guiconfig_panel_spec(self, spec, context='main window'):
     # recursively check a panel spec
     if isinstance(
             spec,
         (guicfg.hsplit, guicfg.vsplit, guicfg.hbox, guicfg.vbox)):
         for child in spec.children:
             self.check_guiconfig_panel_spec(child, context)
     elif isinstance(spec, guicfg.tabbed):
         for child in spec.children:
             self.check_guiconfig_panel_spec(child[1], context)
     elif isinstance(spec, guicfg.docked):
         self.check_guiconfig_panel_spec(spec[0])
         for child in spec[1]:
             if not (isinstance(child, tuple) and len(child) == 2):
                 self.log_error(
                     'dock item should be a (name, panel) tuple,'
                     ' found %r', child)
             else:
                 self.check_guiconfig_panel_spec(child[1], context)
     elif isinstance(spec, guicfg.panel):
         try:
             cls = importString(spec.clsname)
         except Exception as err:
             self.log_error('class %r for %s not importable: %s',
                            spec.clsname, context, err)
         else:
             if qt and not issubclass(cls, Panel):
                 self.log.warning(
                     'class %r for %s is not a Panel '
                     'subclass', spec.clsname, context)
         self.validate_setup_spec(spec)
     else:
         self.log_error('found unsupported panel item %r', spec)
Ejemplo n.º 5
0
    def __init__(self, parent, client, options):
        LokiPanelBase.__init__(self, parent, client, options)
        loadUi(self,
               findResource('nicos_ess/loki/gui/ui_files/scriptbuilder.ui'))

        self.window = parent
        self.runBtn.setVisible(False)
        self.mapping = {}
        self.expertmode = self.mainwindow.expertmode

        self._cmdlet = self.sender()
        self._layout = self.frame.layout()
        self.index = self._layout.indexOf(self._cmdlet)

        self.initialise_connection_status_listeners()

        modules = options.get('modules', [])
        for module in modules:
            importString(module)  # should register cmdlets

        for cmdlet in all_cmdlets:

            def callback(on, cmdlet=cmdlet):
                inst = cmdlet(self, self.client)
                inst.cmdletUp.connect(self.on_cmdletUp)
                inst.cmdletDown.connect(self.on_cmdletDown)
                inst.cmdletRemove.connect(self.on_cmdletRemove)
                self.runBtn.setVisible(True)
                self.frame.layout().insertWidget(
                    self.frame.layout().count() - 2, inst)

            action = QAction(cmdlet.name, self)
            action.triggered.connect(callback)
            self.mapping.setdefault(cmdlet.category, []).append(action)

        for category in all_categories[::-1]:
            if category not in self.mapping:
                return
            toolbtn = QToolButton(self)
            toolbtn.setText(category)
            toolbtn.setPopupMode(QToolButton.InstantPopup)
            menu = QMenu(self)
            menu.addActions(self.mapping[category])
            toolbtn.setMenu(menu)
            self.btnLayout.insertWidget(1, toolbtn)
Ejemplo n.º 6
0
    def __init__(self, parent, client, options):
        Panel.__init__(self, parent, client, options)
        loadUi(self, self.ui)

        self.window = parent
        self.mapping = {}
        self.current_cmdlet = None
        self.expertmode = self.mainwindow.expertmode

        # collect values of all cmdlets that have been added
        # so that the common fields carry over to the next cmdlet
        self.value_collection = {}

        self.commandInput.history = self.cmdhistory
        self.commandInput.completion_callback = self.completeInput
        self.console = None

        client.initstatus.connect(self.on_client_initstatus)
        client.mode.connect(self.on_client_mode)
        client.simresult.connect(self.on_client_simresult)

        modules = options.get('modules', [])
        for module in modules:
            importString(module)  # should register cmdlets

        for cmdlet in all_cmdlets:
            action = QAction(cmdlet.name, self)

            def callback(on, cmdlet=cmdlet):
                self.selectCmdlet(cmdlet)

            action.triggered.connect(callback)
            self.mapping.setdefault(cmdlet.category, []).append(action)

        for category in all_categories[::-1]:
            if category not in self.mapping:
                continue
            toolbtn = QToolButton(self)
            toolbtn.setText(category)
            toolbtn.setPopupMode(QToolButton.InstantPopup)
            menu = QMenu(self)
            menu.addActions(self.mapping[category])
            toolbtn.setMenu(menu)
            self.btnLayout.insertWidget(1, toolbtn)
Ejemplo n.º 7
0
def runTool(window, tconfig):
    """Run a tool from *tconfig*

    If it is a tool dialog, use *window* as the parent.
    """
    if isinstance(tconfig, tool):
        try:
            toolclass = importString(tconfig.clsname)
        except ImportError:
            window.showError('Could not import class %r.' % tconfig.clsname)
        else:
            dialog = toolclass(window, window.client, **tconfig.options)
            dialog.setWindowModality(Qt.NonModal)
            dialog.setAttribute(Qt.WA_DeleteOnClose, True)
            dialog.show()
    elif isinstance(tconfig, cmdtool):
        try:
            createSubprocess(tconfig.cmdline)
        except Exception as err:
            window.showError('Could not execute command: %s' % err)
Ejemplo n.º 8
0
    def check_guiconfig_tool_spec(self, spec):
        # recursively check a tool spec
        if not isinstance(spec, (guicfg.tool, guicfg.cmdtool, guicfg.menu)):
            self.log_error('tool spec %r is not a tool() or cmdtool()', spec)

        if isinstance(spec, guicfg.menu):
            for tool in spec.items:
                self.check_guiconfig_tool_spec(tool)

        if isinstance(spec, guicfg.tool):
            try:
                cls = importString(spec.clsname)
            except Exception as err:
                self.log_error('class %r for tool %r not importable: %s',
                               spec.clsname, spec.name, err)
            else:
                if qt and not issubclass(cls, (qt.QDialog, qt.QMainWindow)):
                    self.log.warning(
                        'class %r for tool %r is not a QDialog or'
                        ' QMainWindow', spec.clsname, spec.name)
            self.validate_setup_spec(spec)
Ejemplo n.º 9
0
 def check_guiconfig_panel_spec(self, spec, context='main window'):
     qt5_incompatibles = [
         'nicos.clients.gui.panels.liveqwt.LiveDataPanel',
     ]
     # recursively check a panel spec
     if isinstance(
             spec,
         (guicfg.hsplit, guicfg.vsplit, guicfg.hbox, guicfg.vbox)):
         for child in spec.children:
             self.check_guiconfig_panel_spec(child, context)
     elif isinstance(spec, guicfg.tabbed):
         for child in spec.children:
             self.check_guiconfig_panel_spec(child[1], context)
     elif isinstance(spec, guicfg.docked):
         self.check_guiconfig_panel_spec(spec[0])
         for child in spec[1]:
             if not (isinstance(child, tuple) and len(child) == 2):
                 self.log_error(
                     'dock item should be a (name, panel) tuple,'
                     ' found %r', child)
             else:
                 self.check_guiconfig_panel_spec(child[1], context)
     elif isinstance(spec, guicfg.panel):
         if os.environ.get('NICOS_QT', 4) == '5' and \
            spec.clsname in qt5_incompatibles:
             self.log.warning('%r is not compatible with QT5', spec.clsname)
             return
         try:
             cls = importString(spec.clsname)
         except Exception as err:
             self.log_error('class %r for %s not importable: %s',
                            spec.clsname, context, err)
         else:
             if qt and not issubclass(cls, Panel):
                 self.log.warning(
                     'class %r for %s is not a Panel '
                     'subclass', spec.clsname, context)
         self.validate_setup_spec(spec)
     else:
         self.log_error('found unsupported panel item %r', spec)
Ejemplo n.º 10
0
    def check(self):
        # check syntax
        try:
            with open(self.filename, encoding='utf-8') as fp:
                self.code = fp.read()
            exec(self.code, self.ns)
            self.ast = ast.parse(self.code)
        except SyntaxError as e:
            msg = 'SyntaxError:\t%s' % e.msg
            msg += '\n|line: %s : %s ' % (e.lineno,
                                          e.text.strip() if e.text else '')
            self.log_error(msg, extra={'line': e.lineno})
            return self.good
        except Exception as e:
            self.log_exception(e)
            return self.good
        self.log.info('syntax ok')
        self.setup_info[self.setupname] = self.ns

        if self.is_guiconfig:
            return self.check_guiconfig()

        # check for valid group
        group = self.ns.get('group', 'optional')
        if group not in SETUP_GROUPS:
            self.log_error('invalid setup group %r',
                           group,
                           extra=self.find_global('group'))

        # check for a description
        description = self.ns.get('description', None)
        if description in (None, ''):
            self.log_error('missing user-friendly setup description',
                           extra=self.find_global('description'))

        self.ns['devices'] = fixup_stacked_devices(self,
                                                   self.ns.get('devices', {}))
        # check if devices are duplicated
        if group != 'special':
            devs = self.ns.get('devices', {})
            for devname in devs:
                if devname not in self.devs_seen:
                    self.devs_seen[devname] = self.setupname
                    continue
                # we have a duplicate: it's okay if we exclude the other setup
                # or if we are both basic setups
                other = self.devs_seen[devname]
                self_group = self.ns.get('group', 'optional')
                other_group = self.setup_info[other].get('group', 'optional')
                if self_group == 'basic' and other_group == 'basic':
                    continue
                if other in self.ns.get('excludes', []) or \
                   self.setupname in self.setup_info[other].get('excludes', []):
                    continue
                # it's also ok if it is a sample, experiment, or instrument
                # device
                if devname in ['Sample', 'Exp'] or \
                   'instrument' in devs[devname][1]:
                    continue
                self.log.warning('device name %s duplicate: also in %s',
                                 devname,
                                 self.devs_seen[devname],
                                 extra=self.find_deventry(devname))

        # check for common misspelling of "includes"
        if 'include' in self.ns:
            self.log_error("'include' list should be called 'includes'",
                           extra=self.find_global('include'))

        # check for common misspelling of "excludes"
        if 'exclude' in self.ns:
            self.log_error("'exclude' list should be called 'excludes'",
                           extra=self.find_global('exclude'))

        if os.path.basename(self.filename) == 'startup.py':
            if self.ns.get('includes', []):
                self.log_error("The 'includes' in 'startup.py' must be empty!",
                               extra=self.find_global('includes'))

        # check for types of recognized variables
        for (vname, vtype) in [
            ('description', str),
                # group is already checked against a fixed list
            ('sysconfig', dict),
            ('includes', list),
            ('excludes', list),
            ('modules', list),
            ('devices', dict),
            ('alias_config', dict),
            ('startupcode', str),
            ('extended', dict)
        ]:
            if vname in self.ns and not isinstance(self.ns[vname], vtype):
                self.log_error('%r must be of type %s (but is %s)' %
                               (vname, vtype, type(self.ns[vname])),
                               extra=self.find_global(vname))

        # check for importability of modules
        for module in self.ns.get('modules', []):
            # try to import the device class
            try:
                importString(module)
            except Exception as err:
                self.log_error('module %r not importable: %s',
                               module,
                               err,
                               extra=self.find_global('modules'))

        # check for validity of alias_config
        aliascfg = self.ns.get('alias_config', {})
        if isinstance(aliascfg, dict):  # else we complained above already
            for aliasname, entrydict in aliascfg.items():
                if not (isinstance(aliasname, str)
                        and isinstance(entrydict, dict)):
                    self.log_error(
                        'alias_config entries should map alias '
                        'device names to a dictionary',
                        extra=self.find_global('alias_config'))
                    continue
                for target, prio in entrydict.items():
                    if not (isinstance(target, str) and isinstance(prio, int)
                            and not isinstance(prio, bool)):
                        self.log_error(
                            'alias_config entries should map device '
                            'names to integer priorities',
                            extra=self.find_global('alias_config'))
                        break
                    if target not in self.ns.get('devices', {}):
                        basedev = target.partition('.')[0]
                        if basedev not in self.ns.get('devices'):
                            self.log_error(
                                'alias_config device target should '
                                'be a device from the current setup',
                                extra=self.find_global('alias_config'))
                            break

        # check for validity of display_order
        display_order = self.ns.get('display_order', 50)
        if not isinstance(display_order, int) or \
           not 0 <= display_order <= 100:
            self.log_error(
                'display_order should be an integer between '
                '0 and 100',
                extra=self.find_global('display_order'))

        # check for validity of extended representative
        representative = self.ns.get('extended', {}).get('representative')
        if representative is not None:
            if representative not in self.ns.get('devices', {}):
                self.log_error(
                    'extended["representative"] should be a device '
                    'defined in the current setup',
                    extra=self.find_global('extended'))

        # check for valid device classes (if importable) and parameters
        for devname, devconfig in self.ns.get('devices', {}).items():
            self.check_device(devname, devconfig, group
                              in ('special', 'configdata'))

        # return overall "ok" flag
        return self.good
Ejemplo n.º 11
0
    def check_device(self, devname, devconfig, is_special=False):
        # check for valid name
        if not nicosdev_re.match(devname):
            self.log_error('%s: device name is invalid (must be a valid '
                           'Python identifier)' % devname,
                           extra=self.find_deventry(devname))
        # check for format of config entry
        if not isinstance(devconfig, tuple) or len(devconfig) != 2:
            self.log_error('%s: device entry has wrong format (should be '
                           'device() or a 2-entry tuple)' % devname,
                           extra=self.find_deventry(devname))
            return False
        # try to import the device class
        try:
            cls = importString(devconfig[0])
        except (ImportError, RuntimeError) as err:
            self.log.warning('device class %r for %r not importable: %s',
                             devconfig[0],
                             devname,
                             err,
                             extra=self.find_deventry(devname))
            return
        except Exception as e:
            self.log_error('could not get device class %r for %r:',
                           devconfig[0],
                           devname,
                           extra=self.find_deventry(devname))
            return self.log_exception(e)
        config = devconfig[1]

        # check missing attached devices
        if not hasattr(cls, 'attached_devices'):
            self.log.warning("%s: class %r has no 'attached_devices'", devname,
                             cls.__name__)
        else:
            for aname, ainfo in cls.attached_devices.items():
                try:
                    ainfo.check(None, aname, config.get(aname))
                except ConfigurationError as err:
                    self.log_error('%s: attached device %s (%s) is '
                                   'wrongly configured: %s' %
                                   (devname, aname, cls.__name__, err),
                                   extra=self.find_deventry(devname, aname))
                if aname in config:
                    del config[aname]

        # check missing and unsupported parameter config entries
        if not hasattr(cls, 'parameters'):
            self.log.warning("%s: class %r has no 'parameters'", devname,
                             cls.__name__)
        else:
            if not (config.get('lowlevel', cls.parameters['lowlevel'].default)
                    or issubclass(cls, DeviceAlias)):
                if not config.get('description') and not is_special:
                    self.log.warning('%s: device has no description',
                                     devname,
                                     extra=self.find_deventry(devname))
            for pname, pinfo in cls.parameters.items():
                if pname in config:
                    if pinfo.internal:
                        self.log_error(
                            "%s: '%s' is configured in a setup file although "
                            "declared as internal parameter",
                            devname,
                            pname,
                            extra=self.find_deventry(devname, pname))
                        del config[pname]
                        continue
                    try:
                        pinfo.type(config[pname])
                    except (ValueError, TypeError) as e:
                        self.log_error(
                            '%s: parameter %r value %r is '
                            'invalid: %s',
                            devname,
                            pname,
                            config[pname],
                            e,
                            extra=self.find_deventry(devname, pname))
                    # check value of certain parameters
                    self.check_parameter(devname, pname, config[pname])
                    del config[pname]
                elif pinfo.mandatory:
                    self.log_error('%s: mandatory parameter %r missing',
                                   devname,
                                   pname,
                                   extra=self.find_deventry(devname))
        if config:
            onepar = list(config)[0]
            self.log_error(
                '%s: configured parameters not accepted by the '
                'device class: %s',
                devname,
                ', '.join(config),
                extra=self.find_deventry(devname, onepar))