Я бы хотел обновить следующий код с oauth2client до google-auth .Да, этот код работает и является копией вставки из демоверсии Google на их сайте.
from __future__ import print_function
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
# If modifying these scopes, delete the file token.json.
SCOPES = 'https://www.googleapis.com/auth/presentations.readonly'
# The ID of a sample presentation.
PRESENTATION_ID = '<some id>'
def main():
"""Shows basic usage of the Slides API.
Prints the number of slides and elments in a sample presentation.
"""
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
# delete the file to for authentication and authorization again
store = file.Storage('token.json')
creds = store.get()
if not creds or creds.invalid:
# credentials.json is issued by Google for the application
flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
creds = tools.run_flow(flow, store)
service = build('slides', 'v1', http=creds.authorize(Http()))
# Call the Slides API
presentation = service.presentations().get(presentationId=PRESENTATION_ID).execute()
slides = presentation.get('slides')
print('The presentation contains {} slides:'.format(len(slides)))
for i, slide in enumerate(slides):
print('- Slide #{} contains {} elements.'.format(
i + 1, len(slide.get('pageElements'))))
if __name__ == '__main__':
main()
Я смог обновить большую его часть (я думаю), но не смог найти эквивалент для tools.run_flow
используя google-auth .Ниже моя обновленная версия, и в ней есть все (я думаю), кроме механизма для выполнения tools.run_flow
.Как tools.run_flow
выполняется с помощью google-auth ?
from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession
from googleapiclient.discovery import build
SCOPES = ['https://www.googleapis.com/auth/presentations.readonly']
PRESENTATION_ID = '<some id>'
credentials = service_account.Credentials.from_service_account_file(
"the-json-file.json",
scopes=SCOPES
)
service = build('slides', 'v1', credentials=credentials)
presentation = service.presentations().get(presentationId=PRESENTATION_ID).execute()
slides = presentation.get('slides')
print('The presentation contains {} slides:'.format(len(slides)))
for i, slide in enumerate(slides):
print('- Slide #{} contains {} elements.'.format(
i + 1, len(slide.get('pageElements'))))
Когда я запускаю приведенный выше код с использованием подхода google-auth , я получаю следующий результат:
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://slides.googleapis.com/v1/presentations/<some id>?alt=json returned "The caller does not have permission">
В дополнительном контексте я пытаюсь создать сценарий Python, который обращается к Google Slides для выполнения некоторой обработки содержимого слайдов.Я только читаю, а не пишу в Google Slides.Приведенный выше код является моей попыткой обработать часть аутентификации и авторизации доступа к контенту Google Slides для моей учетной записи GSuite (я являюсь администратором GSuite моей организации).Первый пример с использованием более старого oauth2client прекрасно работает, но поскольку oauth2client устарел и рекомендуется google-auth , я хотел бы сделать это "правильным" способомс использованием самой последней библиотеки.
ОБНОВЛЕНИЕ
Я решил часть своей проблемы с помощью следующего кода:
from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession
from googleapiclient.discovery import build
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
import os
import json
def get_credentials():
CLIENT_SECRET_FILE = '<some file>'
SCOPES = ['https://www.googleapis.com/auth/presentations.readonly']
credentials_path = '<some path>/token.json'
if os.path.exists(credentials_path):
# expect these to be valid. may expire at some point, but should be refreshed by google api client...
return Credentials.from_authorized_user_file(credentials_path, scopes=SCOPES)
else:
flow = InstalledAppFlow.from_client_secrets_file(
CLIENT_SECRET_FILE,
scopes=SCOPES,
redirect_uri='urn:ietf:wg:oauth:2.0:oob')
auth_url, _ = flow.authorization_url(prompt='consent')
print('Please go to this URL and finish the authentication flow: {}'.format(auth_url))
code = input('Enter the authorization code: ')
flow.fetch_token(code=code)
credentials = flow.credentials
credentials_as_dict = {
'token': credentials.token,
'refresh_token': credentials.refresh_token,
'id_token': credentials.id_token,
'token_uri': credentials.token_uri,
'client_id': credentials.client_id,
'client_secret': credentials.client_secret
}
with open(credentials_path, 'w') as file:
file.write(json.dumps(credentials_as_dict))
return credentials
# The ID of a sample presentation.
PRESENTATION_ID = '<some id>'
service = build('slides', 'v1', credentials=get_credentials())
presentation = service.presentations().get(presentationId=PRESENTATION_ID).execute()
slides = presentation.get('slides')
print('The presentation contains {} slides:'.format(len(slides)))
for i, slide in enumerate(slides):
print('- Slide #{} contains {} elements.'.format(
i + 1, len(slide.get('pageElements'))))
Моя проблема сейчас вызываетвеб-браузер, чтобы открыть автоматически.Я могу скопировать и вставить ссылку и получить код вручную, и все это работает.В идеале мне бы хотелось, чтобы автоматически открывался веб-браузер и захватывался токен, как это было в старой библиотеке.
решено
Обновите код раздела впредыдущий пример кода к этому:
flow = InstalledAppFlow.from_client_secrets_file(
CLIENT_SECRET_FILE,
scopes=SCOPES,
redirect_uri='urn:ietf:wg:oauth:2.0:oob')
credentials = flow.run_local_server()
credentials_as_dict = {
'token': credentials.token,
'refresh_token': credentials.refresh_token,
'id_token': credentials.id_token,
'token_uri': credentials.token_uri,
'client_id': credentials.client_id,
'client_secret': credentials.client_secret
}
Веб-браузер открывается автоматически и фиксирует значение токена.Все хорошо.