Esempio n. 1
0
 def setup_parameter_from_dict(parameter: _BaseParameter,
                               options: Dict[str, Any]) -> None:
     for attr, val in options.items():
         if attr in PARAMETER_ATTRIBUTES:
             # set the attributes of the parameter, that map 1 to 1
             setattr(parameter, attr, val)
         # extra attributes that need parsing
         elif attr == 'limits':
             if isinstance(val, str):
                 issue_deprecation_warning(
                     ('use of a comma separated string for the limits '
                      'keyword'),
                     alternative='an array like "[lower_lim, upper_lim]"'
                 )
                 lower, upper = [float(x) for x in val.split(',')]
             else:
                 lower, upper = val
             parameter.vals = validators.Numbers(lower, upper)
         elif attr == 'monitor' and val is True:
             self._monitor_parameters.append(parameter)
         elif attr == 'alias':
             setattr(parameter.instrument, val, parameter)
         elif attr == 'initial_value':
             # skip value attribute so that it gets set last
             # when everything else has been set up
             pass
         else:
             log.warning(f'Attribute {attr} not recognized when '
                         f'instatiating parameter \"{parameter.name}\"')
     if 'initial_value' in options:
         parameter.set(options['initial_value'])
Esempio n. 2
0
def test_assert_deprecated_raises():
    with assert_deprecated(
            'The use of this function is deprecated, because '
            'of this being a test. Use \"a real function\" as an '
            'alternative.'):
        issue_deprecation_warning('use of this function',
                                  'of this being a test', 'a real function')
Esempio n. 3
0
def test_issue_deprecation_warning():
    with warnings.catch_warnings(record=True) as w:
        issue_deprecation_warning('use of this function',
                                  'of this being a test', 'a real function')
    assert issubclass(w[-1].category, QCoDeSDeprecationWarning)
    assert (str(
        w[-1].message) == 'The use of this function is deprecated, because '
            'of this being a test. Use \"a real function\" as an alternative.')
Esempio n. 4
0
def test_deprecated_context_manager():
    with _catch_deprecation_warnings() as ws:
        issue_deprecation_warning('something')
        issue_deprecation_warning('something more')
        warnings.warn('Some other warning')
    assert len(ws) == 2
    with warnings.catch_warnings(record=True) as ws:
        issue_deprecation_warning('something')
        warnings.warn('Some other warning')
    assert len(ws) == 2
Esempio n. 5
0
def test_deprecated_context_manager():
    with _catch_deprecation_warnings() as ws:
        issue_deprecation_warning('something')
        issue_deprecation_warning('something more')
        warnings.warn('Some other warning')
    assert len(ws) == 2

    with pytest.warns(expected_warning=QCoDeSDeprecationWarning) as ws:
        issue_deprecation_warning('something')
        warnings.warn('Some other warning')
    assert len(ws) == 2
Esempio n. 6
0
    def load_instrument(self,
                        identifier: str,
                        revive_instance: bool = False,
                        **kwargs) -> Instrument:
        """
        Creates an :class:`~.Instrument` instance as described by the
        loaded configuration file.

        Args:
            identifier: The identfying string that is looked up in the yaml
                configuration file, which identifies the instrument to be added.
            revive_instance: If ``True``, try to return an instrument with the
                specified name instead of closing it and creating a new one.
            **kwargs: Additional keyword arguments that get passed on to the
                ``__init__``-method of the instrument to be added.
        """
        # try to revive the instrument
        if revive_instance and Instrument.exist(identifier):
            return Instrument.find_instrument(identifier)

        # load file
        # try to reload file on every call. This makes script execution a
        # little slower but makes the overall workflow more convenient.
        self.load_config_file(self.config_file)

        # load from config
        if identifier not in self._instrument_config.keys():
            raise RuntimeError(f'Instrument {identifier} not found in '
                               'instrument config file')
        instr_cfg = self._instrument_config[identifier]

        # TODO: add validation of config for better verbose errors:

        # check if instrument is already defined and close connection
        if instr_cfg.get('enable_forced_reconnect',
                         get_config_enable_forced_reconnect()):
            with suppress(KeyError):
                self.close_and_remove_instrument(identifier)

        # instantiate instrument
        init_kwargs = instr_cfg.get('init', {})
        # somebody might have a empty init section in the config
        init_kwargs = {} if init_kwargs is None else init_kwargs
        if 'address' in instr_cfg:
            init_kwargs['address'] = instr_cfg['address']
        if 'port' in instr_cfg:
            init_kwargs['port'] = instr_cfg['port']
        # make explicitly passed arguments overide the ones from the config
        # file.
        # We are mutating the dict below
        # so make a copy to ensure that any changes
        # does not leek into the station config object
        # specifically we may be passing non pickleable
        # instrument instances via kwargs
        instr_kwargs = deepcopy(init_kwargs)
        instr_kwargs.update(kwargs)
        name = instr_kwargs.pop('name', identifier)

        if 'driver' in instr_cfg:
            issue_deprecation_warning(
                'use of the "driver"-keyword in the station '
                'configuration file',
                alternative='the "type"-keyword instead, prepending the '
                'driver value'
                ' to it')
            module_name = instr_cfg['driver']
            instr_class_name = instr_cfg['type']
        else:
            module_name = '.'.join(instr_cfg['type'].split('.')[:-1])
            instr_class_name = instr_cfg['type'].split('.')[-1]
        module = importlib.import_module(module_name)
        instr_class = getattr(module, instr_class_name)
        instr = instr_class(name, **instr_kwargs)

        def resolve_instrument_identifier(
                instrument: ChannelOrInstrumentBase,
                identifier: str) -> ChannelOrInstrumentBase:
            """
            Get the instrument, channel or channel_list described by a nested
            string.

            E.g: 'dac.ch1' will return the instance of ch1.
            """
            try:
                for level in identifier.split('.'):
                    instrument = checked_getattr(instrument, level,
                                                 (InstrumentBase, ChannelList))
            except TypeError:
                raise RuntimeError(
                    f'Cannot resolve `{level}` in {identifier} to an '
                    f'instrument/channel for base instrument '
                    f'{instrument!r}.')
            return instrument

        def resolve_parameter_identifier(instrument: ChannelOrInstrumentBase,
                                         identifier: str) -> _BaseParameter:
            parts = identifier.split('.')
            if len(parts) > 1:
                instrument = resolve_instrument_identifier(
                    instrument, '.'.join(parts[:-1]))
            try:
                return checked_getattr(instrument, parts[-1], _BaseParameter)
            except TypeError:
                raise RuntimeError(
                    f'Cannot resolve parameter identifier `{identifier}` to '
                    f'a parameter on instrument {instrument!r}.')

        def setup_parameter_from_dict(parameter: _BaseParameter,
                                      options: Dict[str, Any]) -> None:
            for attr, val in options.items():
                if attr in PARAMETER_ATTRIBUTES:
                    # set the attributes of the parameter, that map 1 to 1
                    setattr(parameter, attr, val)
                # extra attributes that need parsing
                elif attr == 'limits':
                    if isinstance(val, str):
                        issue_deprecation_warning(
                            ('use of a comma separated string for the limits '
                             'keyword'),
                            alternative='an array like "[lower_lim, upper_lim]"'
                        )
                        lower, upper = [float(x) for x in val.split(',')]
                    else:
                        lower, upper = val
                    parameter.vals = validators.Numbers(lower, upper)
                elif attr == 'monitor' and val is True:
                    self._monitor_parameters.append(parameter)
                elif attr == 'alias':
                    setattr(parameter.instrument, val, parameter)
                elif attr == 'initial_value':
                    # skip value attribute so that it gets set last
                    # when everything else has been set up
                    pass
                else:
                    log.warning(f'Attribute {attr} not recognized when '
                                f'instatiating parameter \"{parameter.name}\"')
            if 'initial_value' in options:
                parameter.set(options['initial_value'])

        def add_parameter_from_dict(instr: InstrumentBase, name: str,
                                    options: Dict[str, Any]) -> None:
            # keep the original dictionray intact for snapshot
            options = copy(options)
            param_type: type = _BaseParameter
            kwargs = {}
            if 'source' in options:
                param_type = DelegateParameter
                kwargs['source'] = resolve_parameter_identifier(
                    instr.root_instrument, options['source'])
                options.pop('source')
            instr.add_parameter(name, param_type, **kwargs)
            setup_parameter_from_dict(instr.parameters[name], options)

        def update_monitor():
            if ((self.use_monitor is None and get_config_use_monitor())
                    or self.use_monitor):
                # restart Monitor
                Monitor(*self._monitor_parameters)

        for name, options in instr_cfg.get('parameters', {}).items():
            parameter = resolve_parameter_identifier(instr, name)
            setup_parameter_from_dict(parameter, options)
        for name, options in instr_cfg.get('add_parameters', {}).items():
            parts = name.split('.')
            local_instr = (instr if len(parts) < 2 else
                           resolve_instrument_identifier(
                               instr, '.'.join(parts[:-1])))
            add_parameter_from_dict(local_instr, parts[-1], options)
        self.add_component(instr)
        update_monitor()
        return instr
Esempio n. 7
0
def test_assert_not_deprecated_raises():
    with pytest.raises(AssertionError):
        with assert_not_deprecated():
            issue_deprecation_warning('something')
Esempio n. 8
0
def test_assert_deprecated_does_not_raise_wrong_msg():
    with pytest.raises(AssertionError):
        with assert_deprecated('entirely different message'):
            issue_deprecation_warning('warning')