Google Drive API: How to read the secrets.toml file as a json file?

I’m using the Google Drive API for a project, which now I want to move to Streamlit.

I was using a client_secrets.json to create the API service using a function provided by Google:

CLIENT_SECRET_FILE = 'client_secrets.json'  # πŸ‘ˆ JSON File with the API KEY and other config stuff
API_NAME = 'drive'
API_VERSION = 'v3'
SCOPES = ['https://www.googleapis.com/auth/drive']

#This function expects a json file/route as the "CLIENT_SECRET_FILE" parameter πŸ‘‡
service = Create_Service(CLIENT_SECRET_FILE, API_NAME, API_VERSION, SCOPES)

I know about the secrets.toml and already created it using the content of the client_secrets.json.

Now, when I declare

CLIENT_SECRET_FILE = st.secrets['something']
#or
CLIENT_SECRET_FILE = st.secrets

I get this error:

with open(client_secrets_file, "r") as json_file:
TypeError: expected str, bytes or os.PathLike object, not Secrets

How can I use the Create_Service() function using TOML instead of JSON?

Thanks for your help!!!

Hi @gmepscon, welcome to the Streamlit community!

In this case, when you are using the secrets functionality, you often need to change the authentication method. For example, in this example where we show how to connect Streamlit to a private Google Sheet, there is a method service_account.Credentials.from_service_account_info where you can pass the values in, rather than a JSON file.

If you can post the code or the library you are using, I can quickly look at the Google library documentation and suggest what function it might be.

Best,
Randy

2 Likes

Hello @randyzwitch ! Thank you for your answer, I appreciate it!!

I actually got that working, but another error came up when I tried to deploy the app:

I think it’s got something to do about not running it on the local server anymore. This is the function that contains the error:

def Create_Service(client_secret_file, api_name, api_version, *scopes):
    print(client_secret_file, api_name, api_version, scopes, sep='-')
    CLIENT_SECRET_FILE = client_secret_file
    API_SERVICE_NAME = api_name
    API_VERSION = api_version
    SCOPES = [scope for scope in scopes[0]]
    print(SCOPES)

    cred = None

    pickle_file = f'token_{API_SERVICE_NAME}_{API_VERSION}.pickle'
    # print(pickle_file)

    if os.path.exists(pickle_file):
        with open(pickle_file, 'rb') as token:
            cred = pickle.load(token)

    if not cred or not cred.valid:
        if cred and cred.expired and cred.refresh_token:
            cred.refresh(Request())
        else:
            # ⭐This was solved the original question of my forum post (using .from_client_config)
            # flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES)
            flow = InstalledAppFlow.from_client_config(CLIENT_SECRET_FILE, SCOPES)

            
            # β—πŸ‘‡β—  πŸ†˜
            cred = flow.run_local_server() # Where I think the new error is originating:
            # β—β˜β— πŸ†˜

        with open(pickle_file, 'wb') as token:
            pickle.dump(cred, token)

    try:
        service = build(API_SERVICE_NAME, API_VERSION, credentials=cred)
        print(API_SERVICE_NAME, 'service created successfully')
        return service
    except Exception as e:
        print('Unable to connect.')
        print(e)
        return None

Any ideas on how I might fix this???

Thank you Randy, you are awesome!!

@randyzwitch I am experiencing a similar problem. I am unsure how to adapt my code to have my streamlit app download a Google Drive Folder. I am using this library for a Google-Drive-Folder-Downloader. Can you let me know how to modify this code to make it work for Streamlit?

1 Like

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.