Skip to content
Snippets Groups Projects
Forked from DM / dm-docs
261 commits behind, 839 commits ahead of the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
apsBssApi.py 5.07 KiB
#!/usr/bin/env python

import os
from dm.common.exceptions.configurationError import ConfigurationError
from dm.common.api.dmSudsApi import DmSudsApi
from dm.aps_bss.impl.bssClient import BssClient

class ApsBssApi(DmSudsApi):
    ''' Data Management API for APS Beamline Scheduling System. '''
    def __init__(self, beamlineName=None, username=None, password=None, loginFile=None):
        '''
        Constructor.

        :param beamlineName: beamline name (if not provided, environment variable DM_BEAMLINE_NAME must be set)
        :type beamlineName: str

        :param username: BSS username (if not provided, loginFile must be specified, or environment variable DM_BSS_LOGIN_FILE must be set)
        :type username: str

        :param password: BSS password (if not provided, loginFile must be specified, environment variable DM_BSS_LOGIN_FILE must be set)
        :type password: str

        :param loginFile: BSS login file (not used if username/password are provided; it can be replaced by environment variable DM_BSS_LOGIN_FILE)
        :type loginFile: str

        :raises ConfigurationError: in case beamline name or username/password are not provided, and corresponding environment variables are not set

        Note that environment variable DM_BSS_LOGIN_FILE should contain 
        path to a file containing BSS username and password as a single line in 
        the '<username>|<password>' form.

        >>> api = ApsBssApi(beamlineName='1-ID-B,C,E', username='dm', password='XYZ')
        '''
        DmSudsApi.__init__(self)
        if not username or not password:
            if not loginFile:
                loginFile = os.environ.get('DM_BSS_LOGIN_FILE')
            if loginFile:
                try:
                    # Assume form <username>|<password>
                    tokenList = open(loginFile).readline().split('|')
                    if len(tokenList) == 2:
                        username = tokenList[0].strip()
                        password = tokenList[1].strip()
                except Exception, ex:
                    raise ConfigurationError('Could not determine username/password from BSS login file: %s' % str(ex))
        if not username or not password:
            raise ConfigurationError('Username and/or password were not provided, and DM_BSS_LOGIN_FILE is not set.')

        if not beamlineName:
            beamlineName = os.environ.get('DM_BEAMLINE_NAME')
        if not beamlineName:
            raise ConfigurationError('Beamline name was not provided, and DM_BEAMLINE_NAME is not set.')

        self.beamlineName = beamlineName
        self.bssClient = BssClient(username, password)

    @DmSudsApi.executeSudsCall
    def listRuns(self):
        '''
        List all available runs.

        :returns: list of RunInfo objects

        :raises DmException: for any error

        >>> runs = api.listRuns()
        >>> for run in runs:
        >>>     print run['name']
        '''
        return self.bssClient.listRuns()

    @DmSudsApi.executeSudsCall
    def getCurrentRun(self):
        '''
        Find current run.

        :returns: RunInfo object

        :raises DmException: for any error

        >>> run = api.getCurrentRun()
        '''
        return self.bssClient.getCurrentRun()

    @DmSudsApi.executeSudsCall
    def listBeamlineProposals(self, runName=None):
        '''
        List beamline proposals for a given run.

        :param runName: run name (if not provided, current run name will be used)
        :type runName: str

        :returns: list of ProposalInfo objects

        :raises DmException: for any error

        >>> proposals = api.listBeamlineProposals()
        >>> for proposal in proposals:
        >>>     print proposal['title']
        '''
        if not runName:
            runName = self.getCurrentRun()['name']
        return self.bssClient.listBeamlineProposals(self.beamlineName, runName)

    @DmSudsApi.executeSudsCall
    def getBeamlineProposal(self, proposalId, runName=None):
        '''
        Get beamline proposal with a given id.

        :param proposalId: proposal id
        :type proposalId: str

        :param runName: run name (if not provided, current run name will be used)
        :type runName: str

        :returns: ProposalInfo object

        :raises ObjectNotFound: if proposal with the given id does not exist

        :raises DmException: for any other error

        >>> proposal = api.getBeamlineProposal(42096)
        >>> for experimenter in proposal['experimenters']:
        >>>     print experimenter['badge'], experimenter['lastName'] 
        '''
        if not runName:
            runName = self.getCurrentRun()['name']
        return self.bssClient.getBeamlineProposal(proposalId, self.beamlineName, runName)

#######################################################################
# Testing.
if __name__ == '__main__':
    api = ApsBssApi('1-ID-B,C,E')
    print 'RUNS', api.listRuns()
    print 'CURRRENT RUN: ', api.getCurrentRun()
    print 'PROPOSALS: ', api.listBeamlineProposals()
    print
    print 'FIND PROPOSAL: ', api.getBeamlineProposal(42096)
    print 'FIND PROPOSAL: ', api.getBeamlineProposal(52096)