Aiogoogle

_images/github_64.png

Async Discovery Service Client +

Async Google OAuth2 Client +

Async Google OpenID Connect (Social Sign-in) Client

Discovery Service?

Many of Google’s public APIs are documented/discoverable by a single API called the Discovery Service.

Google’s Discovery Serivce provides machine readable specifications known as discovery documents (similar to Swagger/OpenAPI). e.g. Google Books.

In essence, Aiogoogle is a feature-rich, yet easy to use Pythonic wrapper for discovery documents.

For a list of supported APIs, visit: Google’s APIs Explorer.

Quickstart

List Files on Google Drive

import asyncio
from aiogoogle import Aiogoogle

user_creds = {'access_token': 'an_access_token'}

async def list_files():
    async with Aiogoogle(user_creds=user_creds) as aiogoogle:
        drive_v3 = await aiogoogle.discover('drive', 'v3')
        json_res = await aiogoogle.as_user(
            drive_v3.files.list(),
        )
        for file in json_res['files']:
            print(file['name'])

asyncio.run(list_files())

Download a File from Google Drive

async def download_file(file_id, path):
    async with Aiogoogle(user_creds=user_creds) as aiogoogle:
        drive_v3 = await aiogoogle.discover('drive', 'v3')
        await aiogoogle.as_user(
            drive_v3.files.get(fileId=file_id, download_file=path, alt='media'),
        )
asyncio.run(download_file('abc123', '/home/user/Desktop/my_file.zip'))

Upload a File to Google Drive

async def upload_file(path):
    async with Aiogoogle(user_creds=user_creds) as aiogoogle:
        drive_v3 = await aiogoogle.discover('drive', 'v3')
        await aiogoogle.as_user(
            drive_v3.files.create(upload_file=path)
        )
asyncio.run(upload_file('/home/aiogoogle/Documents/my_cool_gif.gif/'))

List Your Contacts

import asyncio

async def list_contacts():
    aiogoogle = Aiogoogle(user_creds=user_creds)
    people_v1 = await aiogoogle.discover('people', 'v1')
    async with aiogoogle:
        contacts_book = await aiogoogle.as_user(
            people_v1.people.connections.list(
                resourceName='people/me',
                personFields='names,phoneNumbers'
            ),
            full_res=True
        )
    async for page in contacts_book:
        for connection in page['connections']:
            print(connection['names'])
            print(connection['phoneNumbers'])

asyncio.run(list_contacts())

List Calendar Events

async def list_events():
    async with Aiogoogle(user_creds=user_creds) as aiogoogle:
        calendar_v3 = await aiogoogle.discover('calendar', 'v3')
        res = await aiogoogle.as_user(
            calendar_v3.events.list(calendarId='primary')
        )
        pprint.pprint(res)

Check out https://github.com/omarryhan/aiogoogle/tree/master/examples for more.

Library Setup

$ python3.7 -m pip install --user --upgrade aiogoogle

Google Account Setup

  1. Create a project: Google’s APIs and Services dashboard.

  2. Enable an API: API Library.

  3. Create credentials: Credentials wizard.

  4. Pick an API: Google’s APIs Explorer

    Note

    After choosing an API, get the API’s name and version from the URL as they will be needed later.

Usage

Now that Aiogoogle and your Google account are set up, let’s start!

Assuming you chose the Urlshortener-v1 API:

Create a Google API instance

import asyncio
from aiogoogle import Aiogoogle

async def create_api(name, version):
    async with Aiogoogle() as google:
        return await google.discover(name, version)

url_shortener = asyncio.run(
    create_api('urlshortener', 'v1')
)

>>> url_shortener['resources']
{
    'url': {

        'methods':

            'get': ...
            'insert': ...
            'list': ...
}

Browse an API

Now, let’s browse a resource

>>> url_resource = url_shortener.url

>>> url_resource.methods_available

['get', 'insert', 'list']

Sometimes resources have nested resources

>>> url_resource.resources_available

[]

Let’s inspect a method of a resource

>>> list_url = url_resource.list

>>> list_url['description']

"Retrieves a list of URLs shortened by a user."

>>> list_url.optional_parameters

['projection', 'start_token', 'alt', 'fields', 'key', 'oauth_token', 'prettyPrint', 'quotaUser']

>>> list_url.required_parameters

[]

Let’s check out what the ``start_token`` parameter is and how it should look like

>>> list_url.parameters['start_token']

{
    "type": "string",
    "description": "Token for requesting successive pages of results.",
    "location": "query"
}

Finally let’s create a request, that we’ll then send with Aiogoogle

>>> request = list_url(start_token='a_string', key='a_secret_key')

# Equivalent to:

>>> request = url_shortener.url.list(start_token='a_start_token', key='a_secret_key')

>>> request.url

'https://www.googleapis.com/url/history?start_token=a_start_token&key=a_secret_key'

Send a Request

Let’s create a coroutine that shortens URLs

import asyncio
from aiogoogle import Aiogoogle
from pprint import pprint

api_key = 'you_api_key'

async def shorten_urls(long_url):
    async with Aiogoogle(api_key=api_key) as google:
        url_shortener = await google.discover('urlshortener', 'v1')
        short_url = await google.api_key(
            url_shortener.url.insert(
                json=dict(
                    longUrl=long_url
                )
        )

    return short_url

short_url = asyncio.run(shorten_urls('https://www.google.com'))
pprint(short_url)
{
    "kind": "urlshortener#url",
    "id": "https://goo.gl/Dk2j",
    "longUrl": "https://www.google.com/"
}

Send Requests Concurrently:

Now let’s shorten two URLs at the same time

import asyncio
from aiogoogle import Aiogoogle
from pprint import pprint

async def shorten_url(long_urls):
    async with Aiogoogle(api_key=api_key) as google:
        url_shortener = await google.discover('urlshortener', 'v1')
        short_urls = await google.as_api_key(

            url_shortener.url.insert(
                json=dict(
                    longUrl=long_url[0]
                ),

            url_shortener.url.insert(
                json=dict(
                    longUrl=long_url[1]
                )
        )
    return short_urls

short_urls = asyncio.run(
    shorten_url(
        ['https://www.google.com', 'https://www.google.org']
    )
)
pprint(short_urls)
[
    {
        "kind": "urlshortener#url",
        "id": "https://goo.gl/Dk2j",
        "longUrl": "https://www.google.com/"
    },
    {
        "kind": "urlshortener#url",
        "id": "https://goo.gl/Dk23",
        "longUrl": "https://www.google.org/"
    }
]

Send As Client

#!/usr/bin/python3.7

import asyncio, pprint
from aiogoogle import Aiogoogle

api_key = 'abc123'

async def translate_to_latin(words):
    async with Aiogoogle(api_key=api_key) as aiogoogle:
        language = await aiogoogle.discover('translate', 'v2')
        words = dict(q=[words], target='la')
        result = await aiogoogle.as_api_key(
            language.translations.translate(json=words)
        )
    pprint.pprint(result)

if __name__ == '__main__':
    asyncio.run(translate_to_latin('Aiogoogle is awesome'))
{
    "data": {
        "translations": [
            {
                "translatedText": "Aiogoogle est terribilis!",
                # Google probably meant "awesomelis", but whatever..
                "detectedSourceLanguage": "en"
            }
        ]
    }
}

Send As User (Authorization Code Flow)

import asyncio
from aiogoogle import Aiogoole
from pprint import pprint

USER_CREDS = {'access_token': '...'}

async def get_calendar_events():
    async with Aiogoogle(user_creds=USER_CREDS) as aiogoogle:
        calendar_v3 = await aiogoogle.discover('calendar', 'v3')
        result = await aiogoogle.as_user(
            calendar_v3.events.list(
                calendarId="primary",
                maxResults=1
            )
        )
    pprint.pprint(result)

asyncio.run(get_calendar_events())
{
    "kind": "calendar#events",
    "etag": "\"p33c910kumb6ts0g\"",
    "summary": "user@gmail.com",
    "updated": "2018-11-11T22:31:03.463Z",
    "timeZone": "Africa/Cairo",
    "accessRole": "owner",
    "defaultReminders": [
        {
            "method": "popup",
            "minutes": 30
        },
        {
            "method": "email",
            "minutes": 30
        }
    ],
    "nextPageToken": "CigKGjVkcXIxa20wdHJrOW0xMXN0YABIAGNiQgp6yzd4C",
    "items": [
        {
            "kind": "calendar#event",
            "etag": "\"2784256013588000\"",
            "id": "asdasdasdasdasd",
            "status": "confirmed",
            "htmlLink": "https://www.google.com/calendar/event?eid=asdasdasdasdQG0",
            "created": "2014-02-11T14:13:26.000Z",
            "updated": "2014-02-11T14:13:26.794Z",
            "summary": "Do Something",
            "creator": {
                "email": "omarryhan@gmail.com",
                "displayName": "Omar Ryhan",
                "self": true
            },
            "organizer": {
                "email": "omarryhan@gmail.com",
                "displayName": "Omar Ryhan",
                "self": true
            },
            "start": {
                "date": "2014-03-07"
            },
            "end": {
                "date": "2014-03-08"
            },
            "iCalUID": "asdasdasd@google.com",
            "sequence": 0,
            "attendees": [
                {
                    "email": "omarryhan@gmail.com",
                    "displayName": "Omar Ryhan",
                    "organizer": true,
                    "self": true,
                    "responseStatus": "accepted"
                }
            ],
            "reminders": {
                "useDefault": false,
                "overrides": [
                    {
                        "method": "email",
                        "minutes": 450
                    },
                    {
                        "method": "popup",
                        "minutes": 30
                    }
                ]
            }
        }
    ]
}

Authorization and Authentication

Most of Google’s APIs that are supported by the discovery service support these 3 authentication/authorization schemes:

  1. OAuth2

    Should be used whenever you want to access personal information.

    Also, Aiogoogle supports Google OpenID connect.

    OpenID connect is a tiny layer built on top of OAuth2 to make it natively support Authentication, and not just Authorization. (The magic behind Signin with Google)

  2. API key

    Should be used when accessing Public information.

    A simple secret string, that you can get from Google’s Cloud Console

    Note

    For most personal information, an API key won’t be enough.

    You should use OAuth2 instead.

  3. Service Accounts

    For bot to bot communication. See here

    Useful if you run an application on any of Google Cloud Products.

    Note

    Not yet supported by Aiogoogle

OAuth2 Primer

Oauth2 serves as an authorization framework. It supports four main flows:

  1. Authorization code flow:

  2. Client Credentials Flow:

  3. Implicit Grant Flow:
  4. Resource Owner Password Credentials Flow:

Since Aiogoogle only supports Authorization Code Flow, let’s get a little in to it:

Authorization Code Flow

There are three main parties are involved in this flow:

  1. User:
    • represented as aiogoogle.user_creds
  2. Client:
    • represented as aiogoogle.client_creds
    • 3rd party
  3. Resource Server:
    • The service that aiogoogle acts as a client to. e.g. Google Analytics, Youtube, etc.

Here’s a nice ASCII chart showing how this flow works RFC6749 section 4.1 Figure 3.:

+----------+
| Resource |
|   Owner  |
|          |
+----------+
    ^
    |
    (B)
+----|-----+          Client Identifier      +---------------+
|         -+----(A)-- & Redirection URI ---->|               |
|  User-   |                                 | Authorization |
|  Agent  -+----(B)-- User authenticates --->|     Server    |
|          |                                 |               |
|         -+----(C)-- Authorization Code ---<|               |
+-|----|---+                                 +---------------+
|    |                                           ^      v
(A)  (C)                                         |      |
|    |                                           |      |
^    v                                           |      |
+---------+                                      |      |
|         |>---(D)-- Authorization Code ---------'      |
|  Client |          & Redirection URI                  |
|         |                                             |
|         |<---(E)----- Access Token -------------------'
+---------+       (w/ Optional Refresh Token)

OAuth2 Example

Full example here: https://github.com/omarryhan/aiogoogle/blob/master/examples/auth(production_unsafe)/oauth2.py

Install sanic

pip install --user --upgrade sanic

Warning

Do not copy and paste the following snippet as is.

The error and return messages shown below are very verbose and aren’t fit for production.

If you’re performing OAuth2 via Authorization Code Flow, you shouldn’t hand the user their tokens.

Hint

Code reads from top to bottom

./app.py

import sys, os, webbrowser, yaml, json

from sanic import Sanic, response
from sanic.exceptions import ServerError

from aiogoogle import Aiogoogle
from aiogoogle.auth.utils import create_secret

try:
    with open("../keys.yaml", 'r') as stream:
        config = yaml.load(stream)
except Exception as e:
    print('Rename _keys.yaml to keys.yaml')
    raise e

EMAIL = config['user_creds']['email']
CLIENT_CREDS = {
    'client_id': config['client_creds']['client_id'],
    'client_secret': config['client_creds']['client_secret'],
    'scopes': config['client_creds']['scopes'],
    'redirect_uri': 'http://localhost:5000/callback/aiogoogle',
}
state = create_secret()  # Shouldn't be a global hardcoded variable.


LOCAL_ADDRESS = 'localhost'
LOCAL_PORT = '5000'

app = Sanic(__name__)
aiogoogle = Aiogoogle(client_creds=CLIENT_CREDS)

#----------------------------------------#
#                                        #
# **Step A (Check OAuth2 figure above)** #
#                                        #
#----------------------------------------#

@app.route('/authorize')
def authorize(request):
    uri = aiogoogle.oauth2.authorization_url(
        client_creds=CLIENT_CREDS, state=state, access_type='offline', include_granted_scopes=True, login_hint=EMAIL, prompt='select_account'
    )
    # Step A
    return response.redirect(uri)
#----------------------------------------------#
#                                              #
# **Step B (Check OAuth2 figure above)**       #
#                                              #
#----------------------------------------------#
# NOTE:                                        #
#  you should now be authorizing your app @    #
#   https://accounts.google.com/o/oauth2/      #
#----------------------------------------------#

#----------------------------------------------#
#                                              #
# **Step C, D & E (Check OAuth2 figure above)**#
#                                              #
#----------------------------------------------#

# Step C
# Google should redirect current_user to
# this endpoint with a grant code
@app.route('/callback/aiogoogle')
async def callback(request):
    if request.args.get('error'):
        error = {
            'error': request.args.get('error'),
            'error_description': request.args.get('error_description')
        }
        return response.json(error)
    elif request.args.get('code'):
        returned_state = request.args['state'][0]
        # Check state
        if returned_state != state:
            raise ServerError('NO')
        # Step D & E (D send grant code, E receive token info)
        full_user_creds = await aiogoogle.oauth2.build_user_creds(
            grant = request.args.get('code'),
            client_creds = CLIENT_CREDS
        )
        return response.json(full_user_creds)
    else:
        # Should either receive a code or an error
        return response.text("Something's probably wrong with your callback")

if __name__ == '__main__':
    webbrowser.open(
        'http://' + LOCAL_ADDRESS + ':' + LOCAL_PORT + '/authorize'
    )
    app.run(host=LOCAL_ADDRESS, port=LOCAL_PORT, debug=True)

OpenID Connect Example

Full example here: https://github.com/omarryhan/aiogoogle/blob/master/examples/auth(production_unsafe)/openid_connect.py

Warning

Do not copy and paste the following snippet as is.

The error and return messages shown below are very verbose and aren’t fit for production.

If you’re performing OAuth2 via Authorization Code Flow, you shouldn’t hand the user their tokens.

#!/usr/bin/python3.7

import sys, os, webbrowser, yaml, json, pprint

from sanic import Sanic, response
from sanic.exceptions import ServerError

from aiogoogle import Aiogoogle
from aiogoogle.excs import HTTPError
from aiogoogle.auth.utils import create_secret

try:
    with open("../keys.yaml", 'r') as stream:
        config = yaml.load(stream)
except Exception as e:
    print('Rename _keys.yaml to keys.yaml')
    raise e

EMAIL = config['user_creds']['email']
CLIENT_CREDS = {
    'client_id': config['client_creds']['client_id'],
    'client_secret': config['client_creds']['client_secret'],
    'scopes': config['client_creds']['scopes'],
    'redirect_uri': 'http://localhost:5000/callback/aiogoogle',
}
# Shouldn't be a global or a hardcoded variable.
# Instead, should be tied to a session or a user and shouldn't be used more than once
state = create_secret()
nonce = create_secret()


LOCAL_ADDRESS = 'localhost'
LOCAL_PORT = '5000'

app = Sanic(__name__)
aiogoogle = Aiogoogle(client_creds=CLIENT_CREDS)

#----------------------------------------#
#                                        #
# **Step A (Check OAuth2 figure above)** #
#                                        #
#----------------------------------------#

@app.route('/authorize')
def authorize(request):
    if aiogoogle.openid_connect.is_ready(CLIENT_CREDS):
        uri = aiogoogle.openid_connect.authorization_url(
            client_creds=CLIENT_CREDS,
            state=state,
            nonce=nonce,
            access_type='offline',
            include_granted_scopes=True,
            login_hint=EMAIL,
            prompt='select_account'
        )
        # Step A
        return response.redirect(uri)
    else:
        raise ServerError(
            "Client doesn't have enough info for Oauth2"
        )

#----------------------------------------------#
#                                              #
# **Step B (Check OAuth2 figure above)**       #
#                                              #
#----------------------------------------------#
# NOTE:                                        #
#  you should now be authorizing your app @    #
#   https://accounts.google.com/o/oauth2/      #
#----------------------------------------------#

#----------------------------------------------#
#                                              #
# **Step C, D & E (Check OAuth2 figure above)**#
#                                              #
#----------------------------------------------#

# Step C
# Google should redirect current_user to
# this endpoint with a grant code
@app.route('/callback/aiogoogle')
async def callback(request):
    if request.args.get('error'):
        error = {
            'error': request.args.get('error'),
            'error_description': request.args.get('error_description')
        }
        return response.json(error)
    elif request.args.get('code'):
        returned_state = request.args['state'][0]
        # Check state
        if returned_state != state:
            raise ServerError('NO')
        # Step D & E (D send grant code, E receive token info)
        full_user_creds = await aiogoogle.openid_connect.build_user_creds(
            grant=request.args.get('code'),
            client_creds=CLIENT_CREDS,
            nonce=nonce,
            verify=False
        )
        full_user_info = await aiogoogle.openid_connect.get_user_info(full_user_creds)
        return response.text(
            f"full_user_creds: {pprint.pformat(full_user_creds)}\n\nfull_user_info: {pprint.pformat(full_user_info)}"
        )
    else:
        # Should either receive a code or an error
        return response.text("Something's probably wrong with your callback")

if __name__ == '__main__':
    webbrowser.open(
        'http://' + LOCAL_ADDRESS + ':' + LOCAL_PORT + '/authorize'
    )
    app.run(host=LOCAL_ADDRESS, port=LOCAL_PORT, debug=True)

Design

Aiogoogle does not and will not enforce the use of any async/await framework e.g. Asyncio, Curio or Trio. As a result, modules that handle io are made to be easily pluggable.

If you want to use Curio instead of Asyncio:

pip install aiogoogle[curio_asks]

e.g.

import curio

from aiogoogle import Aiogoogle
from aiogoogle.sessions.curio_asks_session import CurioAsksSession

async def main():
    async with Aiogoogle(session_factory=CurioAsksSession) as google:
        youtube = await google.discover('youtube', 'v3')

curio.run(main)

Another e.g.

#!/usr/bin/python3.7

import curio, pprint

from aiogoogle import Aiogoogle
from aiogoogle.sessions.curio_asks_session import CurioAsksSession

async def list_events():
    async with Aiogoogle(user_creds=user_creds, client_creds=client_creds, session_factory=CurioAsksSession) as aiogoogle:
        calendar_v3 = await aiogoogle.discover('calendar', 'v3')
        events = await aiogoogle.as_user(
            calendar_v3.events.list(calendarId='primary'),
        )
    pprint.pprint(events)

if __name__ == '__main__':
    curio.run(list_events)

The same with asyncio would look like this:

#!/usr/bin/python3.7

import asyncio, pprint

from aiogoogle import Aiogoogle
from aiogoogle.sessions.aiohttp_session import AiohttpSession  # Default

async def list_events():
    async with Aiogoogle(user_creds=user_creds, client_creds=client_creds, session_factory=AiohttpSession) as aiogoogle:
        calendar_v3 = await aiogoogle.discover('calendar', 'v3')
        events = await aiogoogle.as_user(
            calendar_v3.events.list(calendarId='primary'),
        )
    pprint.pprint(events)

if __name__ == '__main__':
    asyncio.run(list_events)

And Trio:

pip install aiogoogle[trio_asks]
#!/usr/bin/python3.7

import trio, pprint

from aiogoogle import Aiogoogle
from aiogoogle.sessions.trio_asks_session import TrioAsksSession   # Default

async def list_events():
    async with Aiogoogle(user_creds=user_creds, client_creds=client_creds, session_factory=TrioAsksSession) as aiogoogle:
        calendar_v3 = await aiogoogle.discover('calendar', 'v3')
        events = await aiogoogle.as_user(
            calendar_v3.events.list(calendarId='primary'),
        )
    pprint.pprint(events)

if __name__ == '__main__':
    trio.run(list_events)

API

Aiogoogle

class aiogoogle.client.Aiogoogle(session_factory=<class 'aiogoogle.sessions.aiohttp_session.AiohttpSession'>, api_key=None, user_creds=None, client_creds=None)[source]

Bases: object

Main entry point for Aiogoogle.

This class acts as tiny wrapper around:

  1. Discovery Service v1 API
  2. Aiogoogle’s OAuth2 manager
  3. Aiogoogle’s API key manager
  4. Aiogoogle’s OpenID Connect manager
  5. One of Aiogoogle’s implementations of a session object
Parameters:

Note

In case you want to instantiate a custom session with initial parameters, you can pass an anonymous factory. e.g.

>>> sess = lambda: Session(your_custome_arg, your_custom_kwarg=True)
>>> aiogoogle = Aiogoogle(session_factory=sess)
coroutine as_anon(*requests, timeout=None, full_res=False)[source]

Sends unauthorized requests

Parameters:
  • *requests (aiogoogle.models.Request) – Requests objects typically created by aiogoogle.resource.Method.__call__
  • timeout (int) – Total timeout for all the requests being sent
  • full_res (bool) – If True, returns full HTTP response object instead of returning it’s content
Returns:

Return type:

aiogoogle.models.Response

coroutine as_api_key(*requests, timeout=None, full_res=False)[source]

Sends requests on behalf of self.api_key (OAuth2)

Parameters:
  • *requests (aiogoogle.models.Request) – Requests objects typically created by aiogoogle.resource.Method.__call__
  • timeout (int) – Total timeout for all the requests being sent
  • full_res (bool) – If True, returns full HTTP response object instead of returning it’s content
Returns:

Return type:

aiogoogle.models.Response

coroutine as_user(*requests, timeout=None, full_res=False)[source]

Sends requests on behalf of self.user_creds (OAuth2)

Parameters:
  • *requests (aiogoogle.models.Request) – Requests objects typically created by aiogoogle.resource.Method.__call__
  • timeout (int) – Total timeout for all the requests being sent
  • full_res (bool) – If True, returns full HTTP response object instead of returning it’s content
Returns:

Return type:

aiogoogle.models.Response

coroutine discover(api_name, api_version=None, validate=True)[source]

Donwloads a discovery document from Google’s Discovery Service V1 and sets it a aiogoogle.resource.GoogleAPI

Note

It is recommended that you explicitly specify an API version.

When you leave the API version to None, Aiogoogle uses the list_api method to search for the best fit version of the given API name.

This will result in sending two http requests instead of just one.

Parameters:
  • api_name (str) – API name to discover. e.g.: “youtube”
  • api_version (str) – API version to discover e.g.: “v3” not “3” and not 3
  • validate (bool) – Set this to False to disallow input validation on calling methods
Returns:

An object that will then be used to create API requests

Return type:

aiogoogle.resource.GoogleAPI

Raises:

aiogoogle.excs.HTTPError

coroutine list_api(name, preferred=None, fields=None)[source]

https://developers.google.com/discovery/v1/reference/apis/list

The discovery.apis.list method returns the list all APIs supported by the Google APIs Discovery Service.

The data for each entry is a subset of the Discovery Document for that API, and the list provides a directory of supported APIs.

If a specific API has multiple versions, each of the versions has its own entry in the list.

Example

>>> await aiogoogle.list_api('youtube')

{
    "kind": "discovery#directoryList",
    "discoveryVersion": "v1",
    "items": [
        {
            "kind": "discovery#directoryItem",
            "id": "youtube:v3",
            "name": "youtube",
            "version": "v3",
            "title": "YouTube Data API",
            "description": "Supports core YouTube features, such as uploading videos, creating and managing playlists, searching for content, and much more.",
            "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest",
            "discoveryLink": "./apis/youtube/v3/rest",
            "icons": {
                "x16": "https://www.google.com/images/icons/product/youtube-16.png",
                "x32": "https://www.google.com/images/icons/product/youtube-32.png"
            },
            "documentationLink": "https://developers.google.com/youtube/v3",
            "preferred": true
        }
    ]
}
Parameters:
  • name (str) – Only include APIs with the given name.
  • preferred (bool) – Return only the preferred version of an API. “false” by default.
  • fields (str) – Selector specifying which fields to include in a partial response.
Returns:

Return type:

dict

Raises:

aiogoogle.excs.HTTPError

GoogleAPI

class aiogoogle.resource.GoogleAPI(discovery_document, validate=True)[source]

Bases: object

Creetes a representation of Google API given a discovery document

Parameters:
  • discovery_document (dict) – A discovery document
  • validate (bool) – Whther or not to validate user input again the schema defined in the discovery document
__getattr__(method_or_resource) → aiogoogle.resource.Resource[source]

Returns resources from an API

Note

This method will first check in resources then will check in methods.

Parameters:method_or_resource (str) – name of the top level method or resource

Example

>>> google_service = GoogleAPI(google_service_discovery_doc)
>>> google_service.user

user resource @ google_service.com/api/v1/
Returns:A Resource or a Method
Return type:aiogoogle.resource.Resource, aiogoogle.resource.Method
Raises:AttributeError
__getitem__(k)[source]

Returns items from the discovery document

Example

>>> google_service = GoogleAPI(google_books_discovery_doc)
>>> google_service['name']

'books'

>>> google_service['id']

'books:v1'

>>> google_service['version']

'v1'

>>> google_service['documentationLink']

'https://developers.google.com/books/docs/v1/getting_started'

>>> google_service['oauth2']['scopes']

https://www.googleapis.com/auth/books: {

    description: "Manage your books"

}
Returns:Discovery Document Item
Return type:dict
methods_available

Returns names of the methods provided by this resource

resources_available

Returns names of the resources in a given API if any

Resource

class aiogoogle.resource.Resource(name, resource_specs, global_parameters, schemas, root_url, service_path, batch_path, validate)[source]

Bases: object

__getattr__(method_or_resource)[source]

Returns either a method or a nested resource

Parameters:method_or_resource – Name of the method or resource desired.
Returns:A Resource or a Method
Return type:aiogoogle.resource.Resource, aiogoogle.resource.Methods

Note

This method will first check in nested resources then will check in methods.

Raises:AttributeError
methods_available

Returns the names of the methods that this resource provides

resources_available

Returns the names of the nested resources in this resource

Method

class aiogoogle.resource.Method(name, method_specs, global_parameters, schemas, root_url, service_path, batch_path, validate)[source]

Bases: object

__getitem__(key)[source]

Examples

>>> self['description']

"method description"

>>> self['scopes']

['returns', 'scopes', 'required', 'by', 'this', 'method', 'in', 'a', 'list']

>>> self['supportsMediaDownload']

False

>>> self['supportsMediaUpload']

True

>>> self['httpMethod']

'GET'

Hint:

Using this method with scopes as an argument can be useful for incremental authorization. (Requesting scopes when needed. As opposed to requesting them at once)

for more: https://developers.google.com/identity/protocols/OAuth2WebServer#incrementalAuth

optional_parameters

Optional Parameters

Returns:List of the names of optional parameters this method takes
Return type:list
optional_query_parameters

Optional Query Parameters

Returns:List of the names of optional query parameters this method takes
Return type:list
parameters

Parameters property

Returns:All parameters that this method can take as described in the discovery document
Return type:dict
path_parameters

Path Parameters

Returns:List of the names of path parameters this method takes
Return type:list
query_parameters

Query Parameters

Returns:List of the names of Query parameters this method takes
Return type:list
request

Returns expected request body

required_parameters

Required Parameters

Returns:List of the names of required parameters this method takes
Return type:list
required_query_parameters

Required Query Parameters

Returns:List of the names of required query parameters this method takes
Return type:list
response

Retruns expected response body

Credentials

class aiogoogle.auth.creds.ApiKey[source]

Bases: str

class aiogoogle.auth.creds.UserCreds(access_token=None, refresh_token=None, expires_in=None, expires_at=None, scopes=None, id_token=None, id_token_jwt=None, token_type=None, token_uri=None, token_info_uri=None, revoke_uri=None)[source]

Bases: aiogoogle.utils._dict

OAuth2 User Credentials Dictionary

access_token

str – Access Token

refresh_token

str – Refresh Token

expires_in

int – seconds till expiry from creation

expires_at

str – JSON datetime ISO 8601 expiry datetime

scopes

list – list of scopes owned by access token

id_token

aiogoogle.auth.creds.IdToken – Decoded OpenID JWT

id_token_jwt

str – Encoded OpenID JWT

token_type

str – Bearer

token_uri

str – URI where this token was issued from

token_info_uri

str – URI where one could get more info about this token

revoke_uri

str – URI where this token should be revoked

class aiogoogle.auth.creds.ClientCreds(client_id=None, client_secret=None, scopes=None, redirect_uri=None)[source]

Bases: aiogoogle.utils._dict

OAuth2 Client Credentials Dictionary

Examples

Scopes: [‘openid’, ‘email’, ‘https://www.googleapis.com/auth/youtube.force-ssl’]

Parameters:
  • client_id (str) – OAuth2 client ID
  • client_secret (str) – OAuth2 client secret
  • scopes (list) – List of scopes that this client should request from resource server
  • redirect_uri (str) – client’s redirect uri

Auth Managers

Note

  • These are the default auth managers. They won’t perform any file io.
  • If you want auth managers with file io capabilities, then you’ll have to implement AbstractAuthManager’s interface or inherent from any of this module’s managers.
  • In most cases you won’t need to implement new managers for file io, as by design, credentials are an instance of dict and will only contain json types (str, number, array, JSONSCHEMA datetime and ISO8601 datetime, etc) to make it easily serializable.
class aiogoogle.auth.managers.ApiKeyManager[source]

Bases: aiogoogle.auth.abc.AbstractAPIKeyManager

static authorize(request, key: str) → aiogoogle.models.Request[source]

Adds API Key authorization query argument to URL of a request given an API key

Parameters:
Returns:

Request with API key in URL

Return type:

aiogoogle.models.Request

class aiogoogle.auth.managers.Oauth2Manager(session_factory, verify=True)[source]

Bases: aiogoogle.auth.abc.AbstractOAuth2Manager

__getitem__(key)[source]

Gets Google’s openID configs

Example

  • response_types_supported
  • scopes_supported
  • claims_supported
authorization_url(client_creds, state=None, access_type=None, include_granted_scopes=None, login_hint=None, prompt=None, response_type='code') → str[source]

First step of OAuth2 authoriztion code flow. Creates an OAuth2 authorization URI.

Parameters:
  • client_creds (aiogoogle.auth.creds.ClientCreds) –

    A client_creds object/dictionary containing the following items:

    • client_id
    • scopes
    • redirect_uri
  • state (str) –

    A CSRF token

    • Optional
    • Specifies any string value that your application uses to maintain state between your authorization request and the authorization server’s response.
    • The server returns the exact value that you send as a name=value pair in the hash (#) fragment of the redirect_uri after the user consents to or denies your application’s access request.
    • You can use this parameter for several purposes, such as:
      • Directing the user to the correct resource in your application
      • Sending nonces
      • Mitigating cross-site request forgery.
    • If no state is passed, this method will generate and add a secret token to user_creds['state'].
    • Since your redirect_uri can be guessed, using a state value can increase your assurance that an incoming connection is the result of an authentication request.
    • If you generate a random string or encode the hash of a cookie or another value that captures the client’s state, you can validate the response to additionally ensure that the request and response originated in the same browser, providing protection against attacks such as cross-site request forgery.
  • access_type (str) –

    Indicates whether your application can refresh access tokens when the user is not present at the browser. Options:

    • Optional
    • "online" Default
    • "offline" Choose this for a refresheable/long-term access token
  • include_granted_scopes (bool) –
    • Optional
    • Enables applications to use incremental authorization to request access to additional scopes in context.
    • If you set this parameter’s value to True and the authorization request is granted, then the new access token will also cover any scopes to which the user previously granted the application access.
  • login_hint (str) –
    • Optional
    • If your application knows which user is trying to authenticate, it can use this parameter to provide a hint to the Google Authentication Server.
    • The server uses the hint to simplify the login flow either by prefilling the email field in the sign-in form or by selecting the appropriate multi-login session.
    • Set the parameter value to an email address or sub identifier, which is equivalent to the user’s Google ID.
    • This can help you avoid problems that occur if your app logs in the wrong user account.
  • prompt (str) –
    • Optional
    • A space-delimited, case-sensitive list of prompts to present the user.
    • If you don’t specify this parameter, the user will be prompted only the first time your app requests access.
    • Possible values are:
      • None : Default: Do not display any authentication or consent screens. Must not be specified with other values.
      • 'consent' : Prompt the user for consent.
      • 'select_account' : Prompt the user to select an account.
  • response_type (str) –
    • OAuth2 response type
    • Defaults to Authorization Code Flow response type

Note

  • It is highly recommended that you don’t leave state as None in production.
  • To effortlessly create a random secret to pass it as a state token, you can use aiogoogle.auth.utils.create_secret()

Note

A Note About Scopes:

  • For a list of all of Google’s available scopes: https://developers.google.com/identity/protocols/googlescopes
  • It is recommended that your application requests access to authorization scopes in context whenever possible.
  • By requesting access to user data in context, via incremental authorization, you help users to more easily understand why your application needs the access it is requesting.

Warning

  • When listening for a callback after redirecting a user to the URL returned from this method, take the following into consideration:

    • If your response endpoint renders an HTML page, any resources on that page will be able to see the authorization code in the URL.
    • Scripts can read the URL directly, and the URL in the Referer HTTP header may be sent to any or all resources on the page.
    • Carefully consider whether you want to send authorization credentials to all resources on that page (especially third-party scripts such as social plugins and analytics).
    • To avoid this issue, it’s recommend that the server first handle the request, then redirect to another URL that doesn’t include the response parameters.

Example

from aiogoogle.auth.utils import create_secret
from aiogoogle import ClinetCreds

client_creds = ClientCreds(
    client_id='a_client_id',
    scopes=['first.scope', 'second.scope'],
    redirect_uri='http://localhost:8080'
)

state = create_secret()

auth_uri = oauth2.authorization_url(
    client_creds=client_creds,
    state=state,
    access_type='offline',
    include_granted_scopes=True,
    login_hint='example@gmail.com',
    prompt='select_account'
    )
Returns:An Authorization URI
Return type:(str)
static authorize(request: aiogoogle.models.Request, user_creds: dict) → aiogoogle.models.Request[source]

Adds OAuth2 authorization headers to requests given user creds

Parameters:
Returns:

Request with OAuth2 authorization header

Return type:

aiogoogle.models.Request

static authorized_for_method(method, user_creds) → bool[source]

Checks if oauth2 user_creds dict has sufficient scopes for a method call.

Note

This method doesn’t check whether creds are refreshed or valid.

e.g.

Correct:

is_authorized = authorized_for_method(youtube.video.list)

NOT correct:

is_authorized = authorized_for_method(youtube.video.list())

AND NOT correct:

is_authorized = authorized_for_method(youtube.videos)
Parameters:
Returns:

Return type:

bool

coroutine build_user_creds(grant, client_creds, grant_type='authorization_code') → dict[source]

Second step of Oauth2 authrization code flow. Creates a User Creds object with access and refresh token

Parameters:
  • grant (str) –
    • Aka: “code”.
    • The code received at your redirect URI from the auth callback
  • client_creds (aiogoogle.auth.creds.ClientCreds) –
    • Dict with client_id and client_secret items
  • grant_type (str) –
    • OAuth2 grant type
    • defaults to code (Authorization code flow)
Returns:

User Credentials with the following items:

  • access_token
  • refresh_token
  • expires_in (JSON format ISO 8601)
  • token_type always set to bearer
  • scopes

Return type:

aiogoogle.auth.creds.UserCreds

Raises:

aiogoogle.excs.AuthError – Auth Error

coroutine get_me_info(user_creds)[source]

Gets information of a user given his access token. User must also be the client. (Not sure whether or not that’s the main purpose of this endpoint and how it differs from get_user_info. If someone can confirm/deny this, please edit (or remove) this message and make a pull request)

Parameters:user_creds (aiogoogle.creds.UserCreds) – UserCreds instance with an access token
Returns:Info about the user
Return type:dict
Raises:aiogoogle.excs.HTTPError
coroutine get_token_info(user_creds)[source]

Gets token info given an access token

Parameters:user_creds (aiogoogle.creds.UserCreds) – UserCreds instance with an access token
Returns:Info about the token
Return type:dict
static is_expired(creds) → bool[source]

Checks if user_creds expired

Parameters:user_creds (aiogoogle.auth.creds.UserCreds) – User Credentials
Returns:
Return type:bool
static is_ready(client_creds)[source]

Checks passed client_creds whether or not the client has enough information to perform OAuth2 Authorization code flow

Parameters:client_creds (aiogoogle.auth.creds.ClientCreds) – Client credentials object
Returns:
Return type:bool
coroutine refresh(user_creds, client_creds)[source]

Refreshes user_creds

Parameters:
Returns:

Refreshed user credentials

Return type:

aiogoogle.creds.UserCreds

Raises:

aiogoogle.excs.AuthError – Auth Error

coroutine revoke(user_creds)[source]

Revokes user_creds

In some cases a user may wish to revoke access given to an application. A user can revoke access by visiting Account Settings. It is also possible for an application to programmatically revoke the access given to it. Programmatic revocation is important in instances where a user unsubscribes or removes an application. In other words, part of the removal process can include an API request to ensure the permissions granted to the application are removed.

Parameters:user_creds (aiogoogle.auth.Creds) – UserCreds with an access_token item
Returns:
Return type:None
Raises:aiogoogle.excs.AuthError
class aiogoogle.auth.managers.OpenIdConnectManager(*args, **kwargs)[source]

Bases: aiogoogle.auth.managers.Oauth2Manager, aiogoogle.auth.abc.AbstractOpenIdConnectManager

authorization_url(client_creds, nonce, state=None, prompt=None, display=None, login_hint=None, access_type=None, include_granted_scopes=None, openid_realm=None, hd=None, response_type='code')[source]

First step of OAuth2 authoriztion code flow. Creates an OAuth2 authorization URI.

Parameters:
  • client_creds (aiogoogle.auth.creds.ClientCreds) –

    A client_creds object/dictionary containing the following items:

    • client_id
    • scopes
      • The scope value must begin with the string openid and then include profile or email or both.
    • redirect_uri
  • nonce (str) – A random value generated by your app that enables replay protection.
  • display (str) –
    • An ASCII string value for specifying how the authorization server displays the authentication and consent user interface pages.
    • The following values are specified, and accepted by the Google servers, but do not have any effect on its behavior:
      • page
      • popup
      • touch
      • wap
  • state (str) –

    A CSRF token

    • Optional
    • Specifies any string value that your application uses to maintain state between your authorization request and the authorization server’s response.
    • The server returns the exact value that you send as a name=value pair in the hash (#) fragment of the redirect_uri after the user consents to or denies your application’s access request.
    • You can use this parameter for several purposes, such as:
      • Directing the user to the correct resource in your application
      • Sending nonces
      • Mitigating cross-site request forgery.
    • If no state is passed, this method will generate and add a secret token to user_creds['state'].
    • Since your redirect_uri can be guessed, using a state value can increase your assurance that an incoming connection is the result of an authentication request.
    • If you generate a random string or encode the hash of a cookie or another value that captures the client’s state, you can validate the response to additionally ensure that the request and response originated in the same browser, providing protection against attacks such as cross-site request forgery.
  • access_type (str) –

    Indicates whether your application can refresh access tokens when the user is not present at the browser. Options:

    • Optional
    • "online" Default
    • "offline" Choose this for a refresheable/long-term access token
  • include_granted_scopes (bool) –
    • Optional
    • Enables applications to use incremental authorization to request access to additional scopes in context.
    • If you set this parameter’s value to True and the authorization request is granted, then the new access token will also cover any scopes to which the user previously granted the application access.
  • login_hint (str) –
    • Optional
    • If your application knows which user is trying to authenticate, it can use this parameter to provide a hint to the Google Authentication Server.
    • The server uses the hint to simplify the login flow either by prefilling the email field in the sign-in form or by selecting the appropriate multi-login session.
    • Set the parameter value to an email address or sub identifier, which is equivalent to the user’s Google ID.
    • This can help you avoid problems that occur if your app logs in the wrong user account.
  • prompt (str) –
    • Optional
    • A space-delimited, case-sensitive list of prompts to present the user.
    • If you don’t specify this parameter, the user will be prompted only the first time your app requests access.
    • Possible values are:
      • None : Default: Do not display any authentication or consent screens. Must not be specified with other values.
      • 'consent' : Prompt the user for consent.
      • 'select_account' : Prompt the user to select an account.
  • openid_realm (str) –
    • openid.realm is a parameter from the OpenID 2.0 protocol.
    • It is used in OpenID 2.0 requests to signify the URL-space for which an authentication request is valid.
    • Use openid.realm if you are migrating an existing application from OpenID 2.0 to OpenID Connect.
    • For more details, see Migrating off of OpenID 2.0. https://developers.google.com/identity/protocols/OpenID2Migration
  • hd (str) –
    • The hd (hosted domain) parameter streamlines the login process for G Suite hosted accounts.
    • By including the domain of the G Suite user (for example, mycollege.edu), you can indicate that the account selection UI should be optimized for accounts at that domain.
    • To optimize for G Suite accounts generally instead of just one domain, use an asterisk: hd=*.
    • Don’t rely on this UI optimization to control who can access your app, as client-side requests can be modified.
    • Be sure to validate that the returned ID token has an hd claim value that matches what you expect (e.g. mycolledge.edu).
    • Unlike the request parameter, the ID token claim is contained within a security token from Google, so the value can be trusted.
  • response_type (str) –
    • OAuth2 response type
    • Defaults to Authorization Code Flow response type

Note

It is highly recommended that you don’t leave state as None in production

To effortlessly create a random secret to pass it as a state token, you can use aiogoogle.auth.utils.create_secret()

Note

A Note About Scopes:

  • You can mix OAuth2 scopes with OpenID connect scopes. e.g.: openid email https://www.googleapis.com/auth/urlshortener
  • For a list of all of Google’s available scopes: https://developers.google.com/identity/protocols/googlescopes
  • It is recommended that your application requests access to authorization scopes in context whenever possible.
  • By requesting access to user data in context, via incremental authorization, you help users to more easily understand why your application needs the access it is requesting.

Warning

  • When listening for a callback after redirecting a user to the URL returned from this method, take the following into consideration:

    • If your response endpoint renders an HTML page, any resources on that page will be able to see the authorization code in the URL.
    • Scripts can read the URL directly, and the URL in the Referer HTTP header may be sent to any or all resources on the page.
    • Carefully consider whether you want to send authorization credentials to all resources on that page (especially third-party scripts such as social plugins and analytics).
    • To avoid this issue, it’s recommend that the server first handle the request, then redirect to another URL that doesn’t include the response parameters.

Example

from aiogoogle.auth.utils import create_secret
from aiogoogle import ClinetCreds

client_creds = ClientCreds(
    client_id='a_client_id',
    scopes=['first.scope', 'second.scope'],
    redirect_uri='http://localhost:8080'
)

state = create_secret()
nonce = create_secret()

auth_uri = openid_connect.authorization_url(
    client_creds=client_creds,
    nonce=nonce,
    state=state,
    access_type='offline',
    include_granted_scopes=True,
    login_hint='example@gmail.com',
    prompt='select_account'
    )
Returns:An Authorization URI
Return type:(str)
coroutine build_user_creds(grant, client_creds, grant_type='authorization_code', nonce=None, hd=None, verify=True)[source]

Second step of Oauth2 authrization code flow and OpenID connect. Creates a User Creds object with access and refresh token

Parameters:
  • grant (str) –
    • Aka: “code”.
    • The code received at your redirect URI from the auth callback
  • client_creds (aiogoogle.auth.creds.ClientCreds) –
    • Dict with client_id and client_secret items
  • grant_type (str) –
    • OAuth2 grant type
    • defaults to code (Authorization code flow)
  • nonce (str) –
    • Random value that prevents replay attacks
    • pass the one you used with self.authorization_url() method
  • hd (str) –
    • hosted domain for G-suite
    • used for id_token verification
  • verify (str) –
    • Whether or not to verify the received id_token
    • Unless you’re building a speed critical application AND you’re receiving your tokens directly from Google, you should leave this as True.
Returns:

User Credentials with the following items:

  • access_token
  • refresh_token
  • expires_in (JSON format ISO 8601)
  • token_type always set to bearer
  • scopes

Return type:

aiogoogle.auth.creds.UserCreds

Raises:

aiogoogle.excs.AuthError – Auth Error

coroutine build_user_creds_jwt_auth(assertion, token_uri)[source]

https://tools.ietf.org/html/rfc7523#section-2.2

coroutine build_user_creds_jwt_grant(assertion, token_uri)[source]

Implements the JWT Profile for OAuth 2.0 Authorization Grants.

Parameters:
  • assertion (str) –
    • A single id_token_jwt
  • token_uri (str) –
    • Token URI of your authorization server
Returns:

Return type:

aiogoogle.auth.creds.UserCreds

Raises:

aiogoogle.excs.AuthError

coroutine decode_and_validate(id_token_jwt, client_id=None, nonce=None, hd=None)[source]

Decodes then validates an openid_connect jwt with Google’s oaauth2 certificates

Parameters:
  • id_token_jwt (str) – Found in :class:aiogoogle.auth.creds.UserCreds
  • client_id (str) – If provided will validate token’s audience (‘aud’)
  • nonce (str) – If provided, will validate the nonce provided at authorization
  • hd (str) – If provided, will validate client’s hosted domain
Returns:

Decoded OpenID connect JWT

Return type:

dict

coroutine get_token_info_jwt(user_creds)[source]

get token info using id_token_jwt instead of access_token self.get_token_info

Parameters:user_creds (aiogoogle.auth.creds.UserCreds) – user_creds with id_token_jwt item
Returns:Information about the token
Return type:dict
coroutine get_user_info(user_creds)[source]

https://developers.google.com/+/web/api/rest/openidconnect/getOpenIdConnect

People: getOpenIdConnect

Get user information after performing an OpenID connect flow.

Use this method instead of people.get (Google+ API) when you need the OpenID Connect format.

This method is not discoverable nor is it in the Google API client libraries.

To learn more, see OpenID Connect for sign-in. https://developers.google.com/+/web/api/rest/openidconnect/index.html

Example

>>> await get_user_info(user_creds)
{
    "kind": "plus#personOpenIdConnect",
    "gender": string,
    "sub": string,
    "name": string,
    "given_name": string,
    "family_name": string,
    "profile": string,
    "picture": string,
    "email": string,
    "email_verified": "true",
    "locale": string,
    "hd": string
}
Parameters:user_creds (aiogoogle.auth.creds.UserCreds) – User credentials

Exceptions

exception aiogoogle.excs.AiogoogleError[source]

Bases: Exception

exception aiogoogle.excs.AuthError(msg, req=None, res=None)[source]

Bases: aiogoogle.excs.HTTPError

exception aiogoogle.excs.HTTPError(msg, req=None, res=None)[source]

Bases: aiogoogle.excs.AiogoogleError

exception aiogoogle.excs.ValidationError[source]

Bases: aiogoogle.excs.AiogoogleError

Raised when the validate flag is set true and a validation error occurs

Models

class aiogoogle.models.MediaDownload(file_path)[source]

Bases: object

Media Download

Parameters:file_path (str) – Full path of the file to be downloaded
class aiogoogle.models.MediaUpload(file_path, upload_path=None, mime_range=None, max_size=None, multipart=False, chunk_size=None, resumable=None, validate=True)[source]

Bases: object

Media Upload

Parameters:
  • file_path (str) – Full path of the file to be uploaded
  • upload_path (str) – The URI path to be used for upload. Should be used in conjunction with the rootURL property at the API-level.
  • mime_range (list) – list of MIME Media Ranges for acceptable media uploads to this method.
  • max_size (int) – Maximum size of a media upload in bytes
  • multipart (bool) – True if this endpoint supports upload multipart media.
  • chunksize (int) – Size of a chunk of bytes that a session should read at a time when uploading in multipart.
  • resumable (aiogoogle.models.ResumableUplaod) – A ResumableUpload object
  • validate (bool) – Whether or not a session should validate the upload size before sending
class aiogoogle.models.Request(method=None, url=None, batch_url=None, headers=None, json=None, data=None, media_upload=None, media_download=None, timeout=None, callback=None)[source]

Bases: object

Request class for the whole library. Auth Managers, GoogleAPI and Sessions should all use this.

Note

For HTTP body, only pass one of the following params:

  • json: json as a dict
  • data: www-url-form-encoded form as a dict/ bytes/ text/
Parameters:
  • method (str) – HTTP method as a string (upper case) e.g. ‘GET’
  • url (str) – full url as a string. e.g. ‘https://example.com/api/v1/resource?filter=filter#something
  • batch_url (str) – full url of for sending this request in a batch
  • json (dict) – json as a dict
  • data (any) – www-url-form-encoded form as a dict/ bytes/ text/
  • headers (dict) – headers as a dict
  • media_download (aiogoogle.models.MediaDownload) – MediaDownload object
  • media_upload (aiogoogle.models.MediaUpload) – MediaUpload object
  • timeout (int) – Individual timeout for this request
  • callback (callable) – Synchronous callback that takes the content of the response as the only argument. Should also return content.
classmethod batch_requests(*requests)[source]

Given many requests, will create a batch request per https://developers.google.com/discovery/v1/batch

Parameters:*requests (aiogoogle.models.Request) – Request objects
Returns:
Return type:aiogoogle.models.Request
classmethod from_response(response)[source]
class aiogoogle.models.Response(status_code=None, headers=None, url=None, json=None, data=None, reason=None, req=None, download_file=None, upload_file=None, session_factory=None)[source]

Bases: object

Respnse Object

Parameters:
  • status_code (int) – HTTP Status code
  • headers (dict) – HTTP response headers
  • url (str) – Request URL
  • json (dict) – Json Response if any
  • data (any) – data
  • reason (str) – reason for http error if any
  • req (aiogoogle.models.Request) – request that caused this response
  • download_file (str) – path of the download file specified in the request
  • upload_file (str) – path of the upload file specified in the request
  • session_factory (aiogoogle.sessions.abc.AbstractSession) – A callable implementation of aiogoogle’s session interface
content

any – equals either self.json or self.data

__call__(session_factory=None, req_token_name=None, res_token_name=None, json_req=False)[source]

Returns a generator that yields the contents of the next pages if any (and this page as well)

Parameters:
  • session_factory (aiogoogle.sessions.abc.AbstractSession) – A session factory
  • req_token_name (str) –
    • name of the next_page token in the request
    • Default: “pageToken”
  • res_token_name (str) –
    • name of the next_page token in json response
    • Default: “nextPageToken”
  • json_req (dict) – Normally, nextPageTokens should be sent in URL query params. If you want it in A json body, set this to True
Returns:

self._next_page_generator (staticmethod)

Return type:

async generator

content
error_msg
next_page(req_token_name=None, res_token_name=None, json_req=False) → aiogoogle.models.Request[source]

Method that returns a request object that requests the next page of a resource

Parameters:
  • req_token_name (str) –
    • name of the next_page token in the request
    • Default: “pageToken”
  • res_token_name (str) –
    • name of the next_page token in json response
    • Default: “nextPageToken”
  • json_req (dict) – Normally, nextPageTokens should be sent in URL query params. If you want it in A json body, set this to True
Returns:

Return type:

A request object (aiogoogle.models.Request)

raise_for_status()[source]
class aiogoogle.models.ResumableUpload(file_path, multipart=None, chunk_size=None, upload_path=None)[source]

Bases: object

Resumable Upload Object. Works in conjuction with media upload

Parameters:
  • file_path (str) – Full path of the file to be uploaded
  • upload_path (str) – The URI path to be used for upload. Should be used in conjunction with the rootURL property at the API-level.
  • multipart (bool) – True if this endpoint supports upload multipart media.
  • chunksize (int) – Size of a chunk of bytes that a session should read at a time when uploading in multipart.

Utils

aiogoogle.auth.utils.create_secret(bytes_length=32)[source]

Validate

A simple instance validation module for Discovery schemas. Unfrtunately, Google uses a slightly modified version of JSONschema draft3 (mix of jsonschema and protobuff). As a result, using an external library to validate Discovery schemas will raise lots of errors. I tried to modify the popular: https://github.com/Julian/jsonschema to make it work with Google’s version, but it was just too complicated for the relatively simple task on our hands. If you face any problems with aiogoogle’s validation, you can always turn it off by either passing: method.__call__(validate=False) or turning it off for the whole API by passing aiogoogle.discover(validate=False)

This module misses a lot of the features provided with more advanced jsonschema validators e.g.

  1. collecting all validation errors and raising them all at once
  2. more descriptive errors with nice tracebacks
  3. Validating repeatable instances
  4. additionalItems

and more: https://tools.ietf.org/html/draft-zyp-json-schema-03

aiogoogle.validate.validate(instance, schema, schemas=None, schema_name=None)[source]
Parameters:
  • Instance – Instance to validate
  • schema – schema to validate instance against
  • schemas – Full schamas dict to resolve refs if any
  • schema_name – Name of the schema (Useful if you want more meaningful errors)

Sessions

class aiogoogle.sessions.aiohttp_session.AiohttpSession(*args, **kwargs)[source]

Bases: aiohttp.client.ClientSession, aiogoogle.sessions.abc.AbstractSession

class aiogoogle.sessions.curio_asks_session.CurioAsksSession(*args, **kwargs)[source]

Bases: asks.sessions.Session, aiogoogle.sessions.abc.AbstractSession

class aiogoogle.sessions.trio_asks_session.TrioAsksSession(*args, **kwargs)[source]

Bases: asks.sessions.Session, aiogoogle.sessions.abc.AbstractSession

More

  1. For a more efficient use of your quota use partial responses.

  2. Discovery Document:

    One of the main objectives of this library is to act as a layer of abstraction over discovery documents.

    If you find any leaks in this abstraction (which you likely will) and find yourself wanting to know more about the discovery document and how it’s structured,

    then take a look at a basic overview of a discovery document:

    Root
    |__ name
    |__ version
    |__ baseUrl
    |__ Global Parameters
    |__ Schemas
    |__ Resources
        |__ Resources
            |_ Resources
            |_ Methods
        |__ Methods
    |__ Methods
        |_ Path
        |_ Parameters
        |_ Request Body
        |_ Response Body
    

    Full reference:.

Contribute

All contributions are welcome :).

Check: https://github.com/omarryhan/aiogoogle/blob/master/CONTRIBUTING.md for some ideas.