Nico Albers
Nico Albers

Reputation: 1696

how to paginate in drive.permissions.list using google-api-python-client

My Problem

I have a GDrive folder of which I want to list the users having access to it. Unfortunately the API doesn't return more than 100 users and the documented solutions to paginate don't work.

(!) Maybe this is related to testing on shared drives - currently I cannot reproduce on non-shared drive folders unfortunately.

What I Tried so far:

I tried the pagination solution as described in the google docs, e.g. I tried:

file_id = "12abcde"  # my folder ID
request = service.permissions().list(
  fileId=file_id, fields="permissions(type,emailAddress)", supportsAllDrives=True
)
while request is not None:
    activities_doc = request.execute()
    request = service.permissions().list_next(request, activities_doc)

the request in the loop is always None.

The returned body from the initial request as well doesn't match the one described in the docs.

Does somebody have experience on making this work?

Upvotes: 3

Views: 760

Answers (3)

Yukihiko Shinoda
Yukihiko Shinoda

Reputation: 975

This is the shortest code:

def get_permissions(file_id) -> Generator[dict, None, None]:
    fields = "nextPageToken, permissions(type,emailAddress)"
    page_token = ""
    resource = SERVICE.permissions()
    while page_token is not None:
        request = resource.list(fileId=file_id, fields=fields, supportsAllDrives=True, pageToken=page_token)
        permission_list = request.execute()
        yield from permission_list.get("permissions", [])
        page_token = permission_list.get("nextPageToken")


file_id = "12abcde"  # my folder ID
for permission in get_permissions(file_id):
    print(permission)

I confirmed that setting empty string "" into page_token works as without it.
We can omit duplicate definition of function calling in code.

Upvotes: 1

Michael Scheper
Michael Scheper

Reputation: 7088

I haven't used the Drive API, but in a fairly modern Python implementation (e.g. 3.11), I'm pretty sure Giselle's code could be simplified like this:

try:
    service = build('drive', 'v3', credentials=creds)
    permissions_api = service.permissions() # permissions in Giselle's code
    permissions = [] # permission_list in Giselle's code

    request = permissions_api.list(
        fileId='folderID',
        fields='nextPageToken, permissions(type,emailAddress)',
        supportsAllDrives=True)
    while request:
        response = request.execute()
        permissions += response
        # permissions += response.get('permissions', []) maybe this, actually?
        request = permissions_api.list_next(request, response)

except HttpError:
    logging.warning('whoopsie!', exc_info=True)  # TODO

pprint.pp(permissions) # Here they all are

You might actually want to append a submapping of response to permission_list, like in the line I commented out (I'm not sure about the structure), but there shouldn't be any need to mess with pagination tokens in your code. The default pageSize should be fine, too.

Upvotes: 2

Giselle Valladares
Giselle Valladares

Reputation: 2261

to get the full list, you need to use the nextPageToken and place it under the pageToken parameter.

You can get the nextPageToken from the response body by adding it to the requested fields.

You can use the following sample code as reference:

    try:

        service = build('drive', 'v3', credentials=creds)
        file_id = "asdfasdfas"  # my folder ID
        permissions_list = []
        first_request = service.permissions().list(
                fileId=file_id, 
                pageSize=100, 
                supportsAllDrives=True, 
                fields="nextPageToken, permissions(type,emailAddress)"
            ).execute()
        
        permissions_list.append(first_request)

        next_Page_Token = first_request.get('nextPageToken')

        

        while next_Page_Token:

            request = service.permissions().list(
                pageToken = next_Page_Token,
                fileId=file_id,
                pageSize=100, 
                supportsAllDrives=True, 
                fields="nextPageToken, permissions(type,emailAddress)"
            ).execute()
            permissions_list.append(request)
            next_Page_Token = request.get('nextPageToken')

            

    except HttpError as error:
        # TODO(developer) - Handle errors from drive API.
        print(f'An error occurred: {error}')

Update:

This one is a sample using list_next() base in the documentation here:

    try:
        service = build('drive', 'v3', credentials=creds)

        permission_list = []
        token = 'test'

        fileID='folderID'

        request_made =  service.permissions().list(
            fileId=fileID,
            pageSize=100, 
            fields="nextPageToken, permissions(type,emailAddress)",
            supportsAllDrives=True
            )

        request = request_made.execute()
        permission_list.append(request)

        while token:
            nextpage = service.permissions().list_next(
                previous_request=request_made, 
                previous_response=request)
            request = nextpage.execute()
            token = request.get('nextPageToken')
            permission_list.append(request)
            request_made = nextpage


    except HttpError as error:
        # TODO(developer) - Handle errors from drive API.
        print(f'An error occurred: {error}')

Upvotes: 4

Related Questions