def authenticate(self, address): ''' Authenticate with the given address. This will prompt user for password unless valid credentials are already available. Client state will be updated if new tokens are generated. Returns an access token. ''' def _cache_token(token_info, username=None): ''' Helper to update state with new token info and optional username. Returns the latest access token. ''' token_info['expires_at'] = time.time() + float(token_info['expires_in']) - 60.0 del token_info['expires_in'] auth['token_info'] = token_info if username is not None: auth['username'] = username self.save_state() return token_info['access_token'] # Check the cache for a valid token from codalab.client.remote_bundle_client import RemoteBundleClient auth_info = self.state['auth'].get(address, {}) if 'token_info' in auth_info: token_info = auth_info['token_info'] expires_at = token_info.get('expires_at', 0.0) if expires_at > time.time(): # Token is usable but check if it's nearing expiration if expires_at >= (time.time() + 900.0): return token_info['access_token'] # Try to refresh token remote_client = RemoteBundleClient(address, lambda command: None) token_info = remote_client.login('refresh_token', token_info['refresh_token'], auth_info['username']) if token_info is not None: return _cache_token(token_info) # If we get here, a valid token is not already available. auth = self.state['auth'][address] = {} print 'Requesting access at %s' % address print 'Username: '******'credentials', username, password) if token_info is None: raise UsageError("Invalid username or password") return _cache_token(token_info, username)