def test_retry(self): num_retries = 5 resp_seq = [({'status': '500'}, '')] * num_retries resp_seq.append(({'status': '200'}, '{}')) http = HttpMockSequence(resp_seq) model = JsonModel() uri = 'https://www.googleapis.com/someapi/v1/collection/?foo=bar' method = 'POST' request = HttpRequest(http, model.response, uri, method=method, body='{}', headers={'content-type': 'application/json'}) sleeptimes = [] request._sleep = lambda x: sleeptimes.append(x) request._rand = lambda: 10 request.execute(num_retries=num_retries) self.assertEqual(num_retries, len(sleeptimes)) for retry_num in range(num_retries): self.assertEqual(10 * 2**(retry_num + 1), sleeptimes[retry_num])
def test_retry(self): num_retries = 5 resp_seq = [({'status': '500'}, '')] * num_retries resp_seq.append(({'status': '200'}, '{}')) http = HttpMockSequence(resp_seq) model = JsonModel() uri = 'https://www.googleapis.com/someapi/v1/collection/?foo=bar' method = 'POST' request = HttpRequest( http, model.response, uri, method=method, body='{}', headers={'content-type': 'application/json'}) sleeptimes = [] request._sleep = lambda x: sleeptimes.append(x) request._rand = lambda: 10 request.execute(num_retries=num_retries) self.assertEqual(num_retries, len(sleeptimes)) for retry_num in range(num_retries): self.assertEqual(10 * 2**(retry_num + 1), sleeptimes[retry_num])
def write_table(service, spreadsheet_id, sheet_name, table): sheet = service.spreadsheets() range_ = f"{sheet_name}!A1:F{len(table) + 1}" try: sheet.values().get(spreadsheetId=spreadsheet_id, range=range_).execute() except: body = { "requests": { "addSheet": { "properties": { "title": sheet_name } } } } sheet.batchUpdate(spreadsheetId=spreadsheet_id, body=body).execute() body = {"values": table} option = "USER_ENTERED" request = service.spreadsheets().values().update( spreadsheetId=spreadsheet_id, range=range_, valueInputOption=option, body=body) request.execute()
def test_no_retry_fails_fast(self): http = HttpMockSequence([({ 'status': '500' }, ''), ({ 'status': '200' }, '{}')]) model = JsonModel() uri = 'https://www.googleapis.com/someapi/v1/collection/?foo=bar' method = 'POST' request = HttpRequest(http, model.response, uri, method=method, body='{}', headers={'content-type': 'application/json'}) request._rand = lambda: 1.0 request._sleep = lambda _: self.fail( 'sleep should not have been called.') try: request.execute() self.fail('Should have raised an exception.') except HttpError: pass
def test_media_io_base_next_chunk_retries(self): try: import io except ImportError: return f = open(datafile('small.png'), 'r') fd = io.BytesIO(f.read()) upload = MediaIoBaseUpload(fd=fd, mimetype='image/png', chunksize=500, resumable=True) # Simulate 5XXs for both the request that creates the resumable upload and # the upload itself. http = HttpMockSequence([ ({ 'status': '500' }, ''), ({ 'status': '500' }, ''), ({ 'status': '503' }, ''), ({ 'status': '200', 'location': 'location' }, ''), ({ 'status': '500' }, ''), ({ 'status': '500' }, ''), ({ 'status': '503' }, ''), ({ 'status': '200' }, '{}'), ]) model = JsonModel() uri = 'https://www.googleapis.com/someapi/v1/upload/?foo=bar' method = 'POST' request = HttpRequest(http, model.response, uri, method=method, headers={}, resumable=upload) sleeptimes = [] request._sleep = lambda x: sleeptimes.append(x) request._rand = lambda: 10 request.execute(num_retries=3) self.assertEqual([20, 40, 80, 20, 40, 80], sleeptimes)
def delete_broadcast(youtube, id_live): """ Remove a broadcast in Youtube """ request = youtube.liveBroadcasts().delete( id=id_live ) request.execute()
def update_live_in_youtube(youtube, start_time, title, id_live): """ Update livestreams youtube with new data """ from django.utils import timezone now = timezone.now() start_time_utc = dt.fromisoformat(start_time) if start_time_utc < now: start_time = dt.now().strftime("%Y-%m-%dT%H:%M:%S%z") + '+00:00' try: request = youtube.liveBroadcasts().update( part="id,snippet", body={ "id": id_live, "snippet": { "title": title, "scheduledStartTime": start_time } } ) response = request.execute() return response["id"] except HttpError as e: # https://developers.google.com/youtube/v3/live/docs/liveBroadcasts/insert#errors logger.error( "An HTTP error {} occurred:\n{}".format( e.resp.status, e.content)) return None except RefreshError: logger.error("An error occurred with token user in update_live_in_youtube(), id_broadcast: {}".format(id_live)) return None
def delete_video(video_id): # Disable OAuthlib's HTTPS verification when running locally. # *DO NOT* leave this option enabled in production. os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1" api_service_name = "youtube" api_version = "v3" CLIENT_SECRETS_FILE = "CLIENT_SECRETS_FILE.json" CREDENTIALS_PICKLE_FILE = "credentials_file" # Get credentials and create an API client def get_authenticated_service(): if os.path.exists(CREDENTIALS_PICKLE_FILE): with open(CREDENTIALS_PICKLE_FILE, 'rb') as f: credentials = pickle.load(f) else: flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes) credentials = flow.run_console() with open(CREDENTIALS_PICKLE_FILE, 'wb') as f: pickle.dump(credentials, f) return googleapiclient.discovery.build(api_service_name, api_version, credentials=credentials) youtube = get_authenticated_service() request = youtube.videos().delete(id=video_id) response = request.execute()
def search_youtube(item_name, num_queries=5): queries = [" DIY", " Thrift Flip", " Upcycle Tutorial"] search_results = {} for query in queries: search_by = item_name + query request = youtube.search().list(q=search_by, part='snippet', type='video', maxResults=num_queries, pageToken=None) result = request.execute() items = result['items'] for each_item in items: search_results[each_item["snippet"]["title"]] = { "video_url": "https://www.youtube.com/watch?v=" + each_item["id"]["videoId"], "description": each_item["snippet"]["description"], "thumbnail_url": each_item["snippet"]["thumbnails"]["high"]["url"], "title": each_item["snippet"]["title"] } if len(search_results) > 0 and query == " Thrift Flip": break if len(search_results) == 0: return "No upcycling tutorials were found for '" + item_name + ".' Please try searching with a different item name." else: return search_results
def appendRow(sheetid, sheetRange, values): print("-- in appnedRow()") service = gmailLogin() # The A1 notation of a range to search for a logical table of data. # Values will be appended after the last row of the table. range_ = sheetRange # TODO: Update placeholder value. # How the input data should be interpreted. value_input_option = 'RAW' # TODO: Update placeholder value. # How the input data should be inserted. insert_data_option = 'INSERT_ROWS' # TODO: Update placeholder value. # "parameters": { # "AdverseEffect": [ # "Eye allergy" # ], # "AdverseEffectStart": "2017-07-18", # "Dissease": "headake", # "Dose": "mg", # "Medicine": "Aspirin", # "OtherMeds": "only aspirin", # "Remarks": "all", # "StartTime": "10:00:00" request = service.spreadsheets().values().append(spreadsheetId=sheetid, range=range_, valueInputOption=value_input_option, insertDataOption=insert_data_option, body=values) response = request.execute() return response
def getRows(sheetid, sheetRange): print("Get ROWs" + sheetRange) service = gmailLogin() # The A1 notation of a range to search for a logical table of data. # Values will be appended after the last row of the table. range_ = sheetRange # TODO: Update placeholder value. # How values should be represented in the output. # The default render option is ValueRenderOption.FORMATTED_VALUE. value_render_option = 'UNFORMATTED_VALUE' # TODO: Update placeholder value. # How dates, times, and durations should be represented in the output. # This is ignored if value_render_option is # FORMATTED_VALUE. # The default dateTime render option is [DateTimeRenderOption.SERIAL_NUMBER]. #date_time_render_option = '' # TODO: Update placeholder value. request = service.spreadsheets().values().get(spreadsheetId=sheetid, range=range_, valueRenderOption=value_render_option) #, dateTimeRenderOption=date_time_render_option) response = request.execute() if ('values' in response): return response.get("values") else: return ""
def update_video_thumbnail(ID, CREDENTIALS): scopes = [ "https://www.googleapis.com/auth/youtube.readonly", "https://www.googleapis.com/auth/youtube.force-ssl" ] # Disable OAuthlib's HTTPS verification when running locally. # *DO NOT* leave this option enabled in production. os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1" api_service_name = "youtube" api_version = "v3" client_secrets_file = "client.json" # Get credentials and create an API client flow = CREDENTIALS.flow if CREDENTIALS.flow else google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file( client_secrets_file, scopes) CREDENTIALS.flow = flow credentials = CREDENTIALS.credentials if CREDENTIALS.credentials else flow.run_console( ) CREDENTIALS.credentials = credentials youtube = CREDENTIALS.youtube if CREDENTIALS.youtube else googleapiclient.discovery.build( api_service_name, api_version, credentials=credentials) CREDENTIALS.youtube = youtube request = youtube.thumbnails().set( videoId=ID, media_body=MediaFileUpload("thumbnail.jpg")) response = request.execute()
def test_ensure_response_callback(self): m = JsonModel() request = HttpRequest( None, m.response, 'https://www.googleapis.com/someapi/v1/collection/?foo=bar', method='POST', body='{}', headers={'content-type': 'application/json'}) h = HttpMockSequence([ ({'status': 200}, '{}')]) responses = [] def _on_response(resp, responses=responses): responses.append(resp) request.add_response_callback(_on_response) request.execute(http=h) self.assertEqual(1, len(responses))
def identify_image(gcs_uri, max_results=50): """Uses the Vision API to identify the given image Args: gcs_uri: A uri of the form: gs://bucket/object Returns: An array of dicts with information about the picture.. """ batch_request = [{ 'image': { 'source': { 'gcs_image_uri': gcs_uri } }, 'features': [{ 'type': 'LABEL_DETECTION', 'maxResults': max_results, },{ 'type': 'IMAGE_PROPERTIES', 'maxResults': max_results, }] }] service = get_vision_service() request = service.images().annotate(body={ 'requests': batch_request, }) response = request.execute() return_object = { 'meta': response['responses'][0].get('labelAnnotations'), 'colors': response['responses'][0].get('imagePropertiesAnnotation').get('dominantColors').get('colors'), } return return_object
def get_books_data(query): service = build('books', 'v1', developerKey=settings.BOOKS_API) request = service.volumes().list(q=query) response = request.execute() service.close( ) # Close the service to avoid leaving sockets open - security risk # This next line returns the results but without each book's ID or individual info link # book_list = [response['items'][item]['volumeInfo']for item in range(len(response['items']))] # Solution to return book ID and info Link along with other details. book_list = [] for item in response['items']: authors = [] for author in item['volumeInfo']['authors']: authors.append(author) book_list.append({ 'id': item['id'], 'title': item['volumeInfo']['title'], 'authors': authors, 'posterImg': item['volumeInfo']['imageLinks']['thumbnail'], 'link': item['selfLink'], # 'rating': item['volumeInfo']['averageRating'], }) return book_list
def enroll_user(user_info): print("Enrolling user with data (writing to new row in spreadsheet): " + str(user_info)) today = datetime.now().strftime("%Y-%m-%d %I:%M %p") user_info_list = [ user_info['rfid'], user_info['name'], user_info['membership'], user_info['duration'], user_info['enrolled'], user_info['expiration'], user_info['credit'], user_info['tools'], today ] #Writing data to sheet body_ = { "range": "A2:M", "majorDimension": "ROWS", "values": [user_info_list] } request = service.spreadsheets().values().append( spreadsheetId=SPREADSHEET_ID, range='A2:M', insertDataOption="INSERT_ROWS", valueInputOption="RAW", body=body_) response = request.execute() print(response) socketio.emit('rfid_enrolled', {})
def update_user(user_info, row): print("Updating user with data (updating row in spreadsheet): " + str(user_info)) user_info_list = [ user_info['rfid'], user_info['name'], user_info['membership'], user_info['duration'], user_info['enrolled'], user_info['expiration'], user_info['credit'], user_info['tools'] ] #Writing data to sheet range_ = 'A' + str(row + 2) + ':M' + str(row + 2) print("Updating range: " + range_) body_ = { "range": range_, "majorDimension": "ROWS", "values": [user_info_list] } #Then update them request = service.spreadsheets().values().update( spreadsheetId=SPREADSHEET_ID, valueInputOption="RAW", range=range_, body=body_) response = request.execute() print(response) socketio.emit('rfid_enrolled', {})
def search_youtube(search_str): # Youtube API Authentication and generate search request #print('Searching Youtube for:', search_str) youtube = build('youtube', 'v3', developerKey=YOUTUBE_API_KEY) request = youtube.search().list(q=search_str, part='snippet', type='video', maxResults=10) results = request.execute() # Return video title and url for each result youtube_results = [] for item in results['items']: info = {} info['vid_title'] = html.unescape(item['snippet']['title']) info[ 'url'] = 'https://www.youtube.com/watch?v=' + item['id']['videoId'] #print('Analyzing:', info['vid_title'], info['url']) #print(youtube_results) # Get video durations and append to youtube_results video = pafy.new(info['url']) info['duration'] = video.length print('video title:', info['vid_title'], 'video duration:', info['duration']) youtube_results.append(info) return youtube_results
def update_joblist(self): db.connect() self.logger.info('updating job list') data = { 'platform': self.settings['platform'], } request = JobListRequest(self.settings, data=data) response = request.execute() if response is not None: # results contain only unassigned jobs for job in response['results']: # meta_app_uuid and job_type results = AppKitJob.select().where( AppKitJob.meta_app_uuid == job['meta_app_uuid'], AppKitJob.job_type == job['job_type']) result_count = len(results) if result_count > 0: db_job = results.get() db_job.delete_instance() db_job = AppKitJob( uuid=job['uuid'], lc_id=job['id'], meta_app_uuid=job['meta_app_uuid'], meta_app_definition=json.dumps(job['meta_app_definition']), app_version=job['app_version'], platform=job['platform'], job_type=job['job_type'], parameters=json.dumps(job['parameters']), assigned_to=this_computer, ) db_job.save() if job['assigned_to'] == None: assignment_data = { 'assigned_to': this_computer, 'status': 'assigned', } assign_request = JobAssignRequest(self.settings, db_job.lc_id, data=assignment_data) assign_request.execute() db_job.assignment_reported_at = datetime.datetime.now() db_job.save() db.close()
def getVideoList(playlistID, maxVids=5000, perPage=50, filename=''): """ """ videos = [] request = youtube.playlistItems().list( part='contentDetails', maxResults = perPage, playlistId = playlistID) while request is not None and len(videos) < maxVids: response = request.execute() for item in response['items']: vid = item['contentDetails']['videoId'] videos.append(vid) request = youtube.playlistItems().list_next( request, response ) if not filename == '': filetext = '' for vid in videos: filetext += vid + ',\n' print(filetext, file=open( filename + '.csv', 'w')) return videos
def report_build_result(self, job): data = { 'job_result': job.job_result, } files = {} # only append ipa if success is true if job.job_status == 'success': output = json.loads(job.output) ipa_filepath = output['ipa_filepath'] filename = os.path.basename(ipa_filepath) files = { 'ipa_file': { 'filepath': ipa_filepath, } } request = JobReportResultRequest(self.settings, job.lc_id, data=data, files=files) response = request.execute() if response is not None: job.result_reported_at = datetime.datetime.now() job.save()
def test_unicode(self): http = HttpMock(datafile('zoo.json'), headers={'status': '200'}) model = JsonModel() uri = 'https://www.googleapis.com/someapi/v1/collection/?foo=bar' method = 'POST' request = HttpRequest(http, model.response, uri, method=method, body='{}', headers={'content-type': 'application/json'}) request.execute() self.assertEqual(uri, http.uri) self.assertEqual(str, type(http.uri)) self.assertEqual(method, http.method) self.assertEqual(str, type(http.method))
def youtube_playlist(): songs_added = [] songs_not_added = [] while True: try: url = input("Enter the URL\n>>> ").split('list=')[-1] request = youtube.playlistItems().list(part="id,snippet", playlistId=url, maxResults=500) response = request.execute() for item in response['items']: video_id = item['snippet']['resourceId']['videoId'] video_title = item['snippet']['title'] youtube_url = f'https://www.youtube.com/watch?v={video_id}' video = youtube_dl.YoutubeDL({ 'quiet': True }).extract_info(youtube_url, download=False) artist = video['artist'] track = video['track'] if artist is not None and track is not None: songs_not_added.append(f'{artist} {track}') elif artist is None and track is None: songs_added.append(video_title) spotify_search(track, artist, video_title) print( f'{len(songs_added) + len(songs_not_added)} Songs parsed in total!' f'\n{len(songs_not_added)} Songs were added\n{len(songs_added)} Songs were NOT added' ) stats(songs_not_added, songs_added) except: print("Not a valid link")
def search_youtube(search_str): # Youtube API Authentication and generate search request youtube = build('youtube', 'v3', developerKey=YOUTUBE_API_KEY) request = youtube.search().list(q=search_str, part='snippet', type='video', maxResults=10) results = request.execute() # Return video title and url for each result youtube_results = [] for item in results['items']: info = {} info['vid_title'] = html.unescape(item['snippet']['title']) info[ 'url'] = 'https://www.youtube.com/watch?v=' + item['id']['videoId'] #print('Analyzing:', info['vid_title'], info['url']) #print(youtube_results) # Get video durations and append to youtube_results video_id = item['id']['videoId'] searchUrl = "https://www.googleapis.com/youtube/v3/videos?id=" + video_id + "&key=" + YOUTUBE_API_KEY + "&part=contentDetails" response = urllib.request.urlopen(searchUrl).read() data = json.loads(response) duration = data['items'][0]['contentDetails']['duration'] duration = re.findall('\d+', duration) info['duration'] = int(duration[0]) * 60 try: info['duration'] = info['duration'] + int(duration[1]) except: pass #print(info['duration']) youtube_results.append(info) return youtube_results
def update_visit_time(row): print("Updating user's last visit time...") #Writing data to sheet range_ = 'I' + str(row + 2) + ':I' + str(row + 2) print("Updating range: " + range_) today = datetime.now().strftime("%Y-%m-%d %I:%M %p") times = sheet.values().get(spreadsheetId=SPREADSHEET_ID, range=range_).execute()['values'][0][0] print(times) body_ = { "range": range_, "majorDimension": "ROWS", "values": [[today + ", " + times]] } #Then update them request = service.spreadsheets().values().update( spreadsheetId=SPREADSHEET_ID, valueInputOption="RAW", range=range_, body=body_) response = request.execute() print(response)
def main(): # Data needed: # Playlist to modify playlist_id = 'PLM21IsezPrtpxRcY5x6qqMx5NzItQK7LS' # CSV file with order of videos - Use pyTubePlaylist.py to retrieve the videos initially ordered_videos_file = 'negra-consentida-ordered.csv' # Read the ordered CSV file into memory video_file = pandas.read_csv(ordered_videos_file) # Disable OAuthlib's HTTPS verification when running locally. # *DO NOT* leave this option enabled in production. os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1" api_service_name = "youtube" api_version = "v3" client_secrets_file = "client_secret.json" # Get credentials and create an API client flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file( client_secrets_file, scopes) credentials = flow.run_console() youtube = googleapiclient.discovery.build(api_service_name, api_version, credentials=credentials) for row in video_file.itertuples(name='VideoToUpdate'): # While I figure this one out, note that: # [0] = index # [1] = videoId # [2] = videoTitle # [3] = videoURL # [4] = videoPosition # playlist_item_id = row[1] # video_id = row[2] # video_new_order = row[6] - 1 # video_position = row[5] playlist_item_id = getattr(row, 'playlistItemId') video_id = getattr(row, 'videoId') # Substract one from video_new_order, because playlist position is zero-based. video_new_order = getattr(row, 'videoEpisode') - 1 request = youtube.playlistItems().update( onBehalfOfContentOwner=config.content_owner, part="snippet", body={ "id": playlist_item_id, "snippet": { "playlistId": playlist_id, "position": video_new_order, "resourceId": { "kind": "youtube#video", "videoId": video_id } } }) response = request.execute() print(response)
def test_unicode(self): http = HttpMock(datafile('zoo.json'), headers={'status': '200'}) model = JsonModel() uri = 'https://www.googleapis.com/someapi/v1/collection/?foo=bar' method = 'POST' request = HttpRequest( http, model.response, uri, method=method, body='{}', headers={'content-type': 'application/json'}) request.execute() self.assertEqual(uri, http.uri) self.assertEqual(str, type(http.uri)) self.assertEqual(method, http.method) self.assertEqual(str, type(http.method))
def test_ensure_response_callback(self): m = JsonModel() request = HttpRequest( None, m.response, 'https://www.googleapis.com/someapi/v1/collection/?foo=bar', method='POST', body='{}', headers={'content-type': 'application/json'}) h = HttpMockSequence([({'status': 200}, '{}')]) responses = [] def _on_response(resp, responses=responses): responses.append(resp) request.add_response_callback(_on_response) request.execute(http=h) self.assertEqual(1, len(responses))
def get_uploads_id(channel): request = youtube_service.channels().list(part='contentDetails', forUsername=channel) response = request.execute() playlist_id = response['items'][0]['contentDetails']['relatedPlaylists'][ 'uploads'] return playlist_id
def ensure_firewall_rules(compute, project, restfw): name = restfw["name"] delete_firewall_rule(compute, project, name) request = compute.firewalls().insert(project=project, body=restfw) response = request.execute() logger.info(response) op_name = response['name'] logger.info(f'waiting for create filewall rule {op_name=}') wait_for_global_operation(compute, project, op_name)
def getChannelID(username): """ Returns string channel identifier for string of legacy YT username. """ request = youtube.channels().list( part = 'id', forUsername = username) response = request.execute() channelID = response['items'][0]['id'] return channelID
def ResizeDiskGb(self, disk_name, new_size): """Resize a disk to a new size. Note: Only allows size growing. Args: disk_name: string, the name of the disks to be resized. new_size: int, the new size in gigabytes to be resized """ body = {'sizeGb': "%d" % new_size} request = self.compute.disks().resize( project=self.project, zone=self.zone, disk=disk_name, body=body) return request.execute()
def delete_firewall_rule(compute, project, name): try: request = compute.firewalls().delete(project=project, firewall=name) response = request.execute() logger.info(response) op_name = response['name'] logger.info(f'waiting for delete filewall rule {op_name=}') wait_for_global_operation(compute, project, op_name) except HttpError as h: if h.resp.status != 404: raise
def test_media_io_base_next_chunk_retries(self): try: import io except ImportError: return f = open(datafile('small.png'), 'rb') fd = io.BytesIO(f.read()) upload = MediaIoBaseUpload( fd=fd, mimetype='image/png', chunksize=500, resumable=True) # Simulate 5XXs for both the request that creates the resumable upload and # the upload itself. http = HttpMockSequence([ ({'status': '500'}, ''), ({'status': '500'}, ''), ({'status': '503'}, ''), ({'status': '200', 'location': 'location'}, ''), ({'status': '500'}, ''), ({'status': '500'}, ''), ({'status': '503'}, ''), ({'status': '200'}, '{}'), ]) model = JsonModel() uri = 'https://www.googleapis.com/someapi/v1/upload/?foo=bar' method = 'POST' request = HttpRequest( http, model.response, uri, method=method, headers={}, resumable=upload) sleeptimes = [] request._sleep = lambda x: sleeptimes.append(x) request._rand = lambda: 10 request.execute(num_retries=3) self.assertEqual([20, 40, 80, 20, 40, 80], sleeptimes)
def execute(self, user_mode, user_action, route=[], body=[]): action = self.get_action(user_mode, user_action) if action: request = self.make_args(action, route, body) if not request: return status = request.execute() if status: result = request.parse() else: result = request.error return result
def test_no_retry_fails_fast(self): http = HttpMockSequence([ ({'status': '500'}, ''), ({'status': '200'}, '{}') ]) model = JsonModel() uri = 'https://www.googleapis.com/someapi/v1/collection/?foo=bar' method = 'POST' request = HttpRequest( http, model.response, uri, method=method, body='{}', headers={'content-type': 'application/json'}) request._rand = lambda: 1.0 request._sleep = lambda _: self.fail('sleep should not have been called.') try: request.execute() self.fail('Should have raised an exception.') except HttpError: pass