omarryhan/aiogoogle

Requesting Google Drive list with multiple pages always results in user_creds of None

Closed this issue · 3 comments

I have a function, aiog_gfolder_get_children_direct, which returns a list of non-trashed files with a given folder as the parent ID.

async def aiog_gfolder_get_children_direct(aiogoogle, drive_v3, folder_id: str = None):
    """Gets all children of a Google Drive Folder.
    Returns a list of dicts: [{id, name, MIMEtype}].
    see also https://developers.google.com/drive/api/v3/search-files"""

    # init fields and query
    fields = "nextPageToken, files(id, name, trashed, mimeType)"
    q = f"'{folder_id}' in parents and trashed = false"

    # prepare search request
    request = drive_v3.files.list(fields=fields, q=q, supportsAllDrives=True, includeItemsFromAllDrives=True)

    # execute search request
    response = await aiogoogle.as_user(request, full_res=True)

    # return list
    children = []

    # iterate over pages
    async for page in response:
        for file in page["files"]:
            dict_ = {"gid": file["id"],
                     "name": file["name"],
                     "mimeType": file["mimeType"]
                     }
            children.extend([dict_])

    # return list of children dicts
    return children

I have never had issues with this function before. It still works fine on single-page results. But after moving to a new computer, I cannot run this function on any request with that has more than 1 page of results. The error below occurs on any request that spans multiple pages:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/Users/mmfa/py_utilities/mailouts3/frl_notifications_23-24.py", line 127, in main
    output_gfolder_children = await aiog_gfolder_get_children_recursive(aiogoogle=aiogoogle, drive_v3=drive_v3, folder_id=output_gfolder)
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/mmfa/py_utilities/_aiogoogle.py", line 263, in aiog_gfolder_get_children_recursive
    children.extend(await aiog_gfolder_get_children_recursive(aiogoogle=aiogoogle, drive_v3=drive_v3, folder_id=gid))
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/mmfa/py_utilities/_aiogoogle.py", line 253, in aiog_gfolder_get_children_recursive
    children = await aiog_gfolder_get_children_direct(aiogoogle=aiogoogle, drive_v3=drive_v3, folder_id=folder_id)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/mmfa/py_utilities/_aiogoogle.py", line 235, in aiog_gfolder_get_children_direct
    async for page in response:
  File "/Users/mmfa/py_utilities/venv/lib/python3.11/site-packages/aiogoogle/models.py", line 356, in _next_page_generator
    is_refreshed, user_creds = await prev_res.auth_manager.refresh(prev_res.user_creds)
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/mmfa/py_utilities/venv/lib/python3.11/site-packages/aiogoogle/auth/managers.py", line 629, in refresh
    if not self.is_expired(user_creds):
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/mmfa/py_utilities/venv/lib/python3.11/site-packages/aiogoogle/auth/managers.py", line 606, in is_expired
    return _is_expired(creds["expires_at"])
                       ~~~~~^^^^^^^^^^^^^^
TypeError: 'NoneType' object is not subscriptable

It seems like the user_creds object is not being transferred from one page's request to the next page's request.

It seems like the user_creds object is not being transferred from one page's request to the next page's request.

It does seem like it indeed. Is it possible you can identify the version on your old computer? That way I can identify the commit that broke things. Also what's the version on your new computer?

I had the same issue.

From the stacktrace, the problem seemed to be that one call to session.send wasn't given the user_creds argument.

I fixed it by changing the models.py file (line 361) from

prev_res = await sess.send(next_req, full_res=True, auth_manager=prev_res.auth_manager)

to

prev_res = await sess.send(next_req, full_res=True, auth_manager=prev_res.auth_manager, user_creds=prev_res.user_creds)

This fixed the issue for me.
(the problem probably stems from issue #110, where the refresh functions were updated but not the subsequent request calls.)

I apologize as I don't have the time to make a PR to fix right now, @omarryhan can you please check that it is indeed the issue, and that it doesn't happen anywhere else in the code ?
Many thanks for this project, while I'm at it.

Thanks for the input @CyriaqueCCN

This should be fixed in v5.5.0 now

@montessoriforall

Please reopen the issue if it still persists. Thanks!