def test_beckoff_axis_device_class(mockqsbackend): c = Client(database=mockqsbackend) d = load_devices(*c.all_items).__dict__ vh_y = d.get('vh_y') sam_x = d.get('sam_x') assert vh_y.__class__.__name__ == 'BeckhoffAxis' assert sam_x.__class__.__name__ == 'IMS'
def get_qs_objs(expname): """ Gather user objects from the experiment questionnaire. Parameters ---------- expname: ``str`` The experiment's name from the elog Returns ------- objs: ``dict`` Mapping from questionnaire ``python name`` to loaded object. """ logger.debug('get_qs_client(%s)', expname) with safe_load('questionnaire'): expname = expname.lower() qs_client = get_qs_client(expname) # Create namespace if not qs_client.all_devices: logger.warning("No devices found in PCDS Questionnaire for %s", expname) return dict() dev_namespace = load_devices(*qs_client.all_devices, pprint=False) return dev_namespace.__dict__ return {}
def test_qsbackend_with_acromag(mockqsbackend): c = Client(database=mockqsbackend) d = load_devices(*c.all_devices, pprint=False).__dict__ ai1 = d.get('ai_7') ao1 = d.get('ao_6') assert ai1.__class__.__name__ == 'EpicsSignalRO' assert ao1.__class__.__name__ == 'EpicsSignal'
def get_happi_devices(self): """ Request devices from happi based on our designer attributes. This relied on the happi_cfg and happi_names properties being set appropriately. """ if self.happi_names and happi_check(): happi_client = Client.from_config(cfg=self.happi_cfg or None) items = [] for name in self.happi_names: try: search_result = happi_client.search(name=name)[0] except IndexError: raise ValueError( f'Did not find device with name {name} in happi. ' 'Please check your spelling and your database.' ) from None items.append(search_result.item) with no_device_lazy_load(): device_namespace = load_devices(*items, threaded=True) return [ getattr(device_namespace, name) for name in self.happi_names ] return []
def test_load_devices(threaded: bool, post_load: Any, include_load_time: bool): # Create a bunch of devices to load devs = [TimeDevice(name='test_1', prefix='Tst1:This', beamline='TST', device_class='datetime.timedelta', args=list(), days=10, kwargs={'days': '{{days}}', 'seconds': 30}), TimeDevice(name='test_2', prefix='Tst2:This', beamline='TST', device_class='datetime.timedelta', args=list(), days=10, kwargs={'days': '{{days}}', 'seconds': 30}), TimeDevice(name='test_3', prefix='Tst3:This', beamline='TST', device_class='datetime.timedelta', args=list(), days=10, kwargs={'days': '{{days}}', 'seconds': 30}), HappiItem(name='bad', prefix='Not:Here', beamline='BAD', device_class='non.existant')] # Load our devices space = load_devices( *devs, pprint=True, use_cache=False, threaded=threaded, post_load=post_load, include_load_time=include_load_time, ) # Check all our devices are there assert all([create_alias(dev.name) in space.__dict__ for dev in devs]) # Devices were loading properly or exceptions were stored import datetime assert space.test_1 == datetime.timedelta(days=10, seconds=30) assert isinstance(space.bad, ImportError)
def get_happi_objs(db, hutch): """ Get the relevant devices for ``hutch`` from ``db``. This depends on a JSON ``happi`` database stored somewhere in the file system and handles setting up the ``happi.Client`` and querying the data base for devices. Parameters ---------- db: ``str`` Path to database hutch: ``str`` Name of hutch Returns ------- objs: ``dict`` A mapping from device name to device """ # Load the happi Client client = happi.Client(path=db) containers = list() # Find upstream devices based on lightpath configuration beamline_conf = beamlines.get(hutch.upper()) # Something strange is happening if there are no upstream devices if not beamline_conf: logger.warning("Unable to find lightpath for %s", hutch.upper()) beamline_conf = {} # Add the complete hutch beamline beamline_conf[hutch.upper()] = {} # Base beamline for beamline, conf in beamline_conf.items(): # Assume we want hutch devices that are active and in the bounds # determined by the beamline configuration reqs = dict(beamline=beamline, active=True, start=conf.get('start', 0), end=conf.get('end', None)) results = client.search_range(key='z', **reqs) blc = [res.device for res in results] # Add the beamline containers to the complete list if blc: containers.extend(blc) else: logger.warning("No devices found in database for %s", beamline.upper()) # Instantiate the devices needed dev_namespace = load_devices(*containers, pprint=False) return dev_namespace.__dict__
def test_load_devices(): # Create a bunch of devices to load devs = [ TimeDevice(name='Test 1', prefix='Tst1:This', beamline='TST', device_class='datetime.timedelta', args=list(), days=10, kwargs={ 'days': '{{days}}', 'seconds': 30 }), TimeDevice(name='Test 2', prefix='Tst2:This', beamline='TST', device_class='datetime.timedelta', args=list(), days=10, kwargs={ 'days': '{{days}}', 'seconds': 30 }), TimeDevice(name='Test 3', prefix='Tst3:This', beamline='TST', device_class='datetime.timedelta', args=list(), days=10, kwargs={ 'days': '{{days}}', 'seconds': 30 }), Device(name='Bad', prefix='Not:Here', beamline='BAD', device_class='non.existant') ] # Load our devices space = load_devices(*devs, pprint=True) # Check all our devices are there assert all([create_alias(dev.name) in space.__dict__ for dev in devs]) # Devices were loading properly or exceptions were stored import datetime assert space.test_1 == datetime.timedelta(days=10, seconds=30) assert isinstance(space.bad, ImportError)
def get_qs_objs(expname): """ Gather user objects from the experiment questionnaire. Connects to the questionnaire webservice via the ``happi`` ``QSBackend`` using ``psdm_qs_cli`` to collect well-defined devices. There are two possible methods of authentication to the ``QuestionnaireClient``, ``Kerberos`` and ``WS-Auth``. The first is simpler but is not possible for all users, we therefore search for a configuration file named ``web.cfg``, either hidden in the current directory or the users home directory. This should contain the username and password needed to authenticate into the ``QuestionnaireClient``. The format of this configuration file is the standard ``.ini`` structure and should define the username and password like: .. code:: ini [DEFAULT] user = MY_USERNAME pw = MY_PASSWORD Parameters ---------- expname: ``str`` The experiment's name from the elog Returns ------- objs: ``dict`` Mapping from questionnaire ``python name`` to loaded object. """ logger.debug('get_qs_objs(%s)', expname) with safe_load('questionnaire'): expname = expname.lower() # Determine which method of authentication we are going to use. # Search for a configuration file, either in the current directory # or hidden in the users home directory. If not found, attempt to # launch the client via Kerberos cfg = ConfigParser() cfgs = cfg.read(['qs.cfg', '.qs.cfg', os.path.expanduser('~/.qs.cfg'), 'web.cfg', '.web.cfg', os.path.expanduser('~/.web.cfg')]) # Ws-auth if cfgs: user = cfg.get('DEFAULT', 'user', fallback=None) try: pw = cfg.get('DEFAULT', 'pw') except NoOptionError as exc: raise ValueError("Must specify password as 'pw' in " "configuration file") from exc qs_client = happi.Client(database=QSBackend(expname, use_kerberos=False, user=user, pw=pw)) # Kerberos else: qs_client = happi.Client(database=QSBackend(expname, use_kerberos=True)) # Create namespace if not qs_client.all_devices: logger.warning("No devices found in PCDS Questionnaire for %s", expname) return dict() dev_namespace = load_devices(*qs_client.all_devices, pprint=False) return dev_namespace.__dict__ return {}