#!/usr/bin/env python import os from dm.common.exceptions.configurationError import ConfigurationError from dm.common.api.dmApi import DmApi from dm.aps_bss.impl.bssClient import BssClient class ApsBssApi(DmApi): ''' Data Management API for APS Beamline Scheduling System. ''' def __init__(self, beamlineName=None, username=None, password=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, environment variable DM_BSS_LOGIN_FILE must be set) :type username: str :param password: BSS password (if not provided, environment variable DM_BSS_LOGIN_FILE must be set) :type password: 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') ''' DmApi.__init__(self) if not username or not password: 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) @DmApi.execute2 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() @DmApi.execute2 def getCurrentRun(self): ''' Find current run. :returns: RunInfo object :raises DmException: for any error >> run = api.getCurrentRun() ''' return self.bssClient.getCurrentRun() @DmApi.execute2 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) @DmApi.execute2 def getBeamlineProposal(self, proposalId, runName=None): ''' Get beamline proposal with a given id. :param porposalId: proposal id :type runName: 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)