Skip to content

Unable to specify credentials programmatically - "got an unexpected keyword argument 'project_id'" #33

Closed as duplicate of#32
@darrenclark

Description

@darrenclark

I'm getting a TypeError: GSheetsConnection._connect() got an unexpected keyword argument 'project_id' when attempting to load my service account's credentials programmatically (the JSON is stored in GCP Secrets Manager).

The docs for st.connection mention the secrets can be provided as additional keyword args:

Configuration options, credentials, and secrets for connections are combined from the following sources:

  • The keyword arguments passed to this command.
    ...

However that doesn't seem to be working.

I suspect that GSheetsConnection._connect(..) needs to be updated to something like this (untested):

-     def _connect(self) -> GSheetsClient:
+     def _connect(self, **kwargs) -> GSheetsClient:
          """Reads st.connection .streamlit/secrets.toml and returns GSheets
          client based on them."""
-         secrets_dict = self._secrets.to_dict()
+         secrets_dict = {**self._secrets.to_dict(), **kwargs}
          if secrets_dict.get("type", None) == "service_account":
              return GSheetsServiceAccountClient(secrets_dict)
          return GSheetsPublicSpreadsheetClient(secrets_dict)

app.py
import streamlit as st
import json
from streamlit_gsheets import GSheetsConnection
from google.cloud import secretmanager

GOOGLE_CLOUD_PROJECT = "<PROJECT>"
GCP_SA_PRIVATE_KEY_SECRET_NAME = "<SECRET>"

@st.cache_data
def get_credentials():
    client = secretmanager.SecretManagerServiceClient()
    name = f"projects/{GOOGLE_CLOUD_PROJECT}/secrets/{GCP_SA_PRIVATE_KEY_SECRET_NAME}/versions/latest" # noqa
    response = client.access_secret_version(request={"name": name})
    raw_json = response.payload.data.decode("UTF-8")
    parsed_json = json.loads(raw_json)
    # conflicts with other `type` arg to st.connection(...)
    # instead, it's specified in .streamlit/secrets.toml
    parsed_json.pop('type')
    return parsed_json

conn = st.connection(
    "gsheets-demo",
    type=GSheetsConnection,
    **get_credentials()
)

df = conn.read()

for row in df.itertuples():
    st.write(f"{row.field1} has a :{row.field2}:") # pyright: ignore
.streamlit/secrets.toml
[connections.gsheets-demo]
spreadsheet = "https://docs.google.com/spreadsheets/d/<REDACTED>/edit?gid=0#gid=0"

type = "service_account"
# remaining auth loaded at runtime
Stack trace
2025-01-30 08:50:23.761 Uncaught app execution
Traceback (most recent call last):
  File "/Users/darren/Library/Caches/pex/venvs/0e7f7ef52d296012b4e4e08c8db05955cc00c4e1/575ca5ce34ac5d283b0502f9efc6408236868ea9/lib/python3.11/site-packages/streamlit/runtime/scriptrunner/exec_code.py", line 88, in exec_func_with_error_handling
    result = func()
             ^^^^^^
  File "/Users/darren/Library/Caches/pex/venvs/0e7f7ef52d296012b4e4e08c8db05955cc00c4e1/575ca5ce34ac5d283b0502f9efc6408236868ea9/lib/python3.11/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 579, in code_to_exec
    exec(code, module.__dict__)
  File "/Users/darren/Projects/streamlit/app.py", line 22, in <module>
    conn = st.connection(
           ^^^^^^^^^^^^^^
  File "/Users/darren/Library/Caches/pex/venvs/0e7f7ef52d296012b4e4e08c8db05955cc00c4e1/575ca5ce34ac5d283b0502f9efc6408236868ea9/lib/python3.11/site-packages/streamlit/runtime/connection_factory.py", line 415, in connection_factory
    conn = _create_connection(
           ^^^^^^^^^^^^^^^^^^^
  File "/Users/darren/Library/Caches/pex/venvs/0e7f7ef52d296012b4e4e08c8db05955cc00c4e1/575ca5ce34ac5d283b0502f9efc6408236868ea9/lib/python3.11/site-packages/streamlit/runtime/metrics_util.py", line 409, in wrapped_func
    result = non_optional_func(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/darren/Library/Caches/pex/venvs/0e7f7ef52d296012b4e4e08c8db05955cc00c4e1/575ca5ce34ac5d283b0502f9efc6408236868ea9/lib/python3.11/site-packages/streamlit/runtime/connection_factory.py", line 103, in _create_connection
    return __create_connection(name, connection_class, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/darren/Library/Caches/pex/venvs/0e7f7ef52d296012b4e4e08c8db05955cc00c4e1/575ca5ce34ac5d283b0502f9efc6408236868ea9/lib/python3.11/site-packages/streamlit/runtime/caching/cache_utils.py", line 218, in __call__
    return self._get_or_create_cached_value(args, kwargs, spinner_message)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/darren/Library/Caches/pex/venvs/0e7f7ef52d296012b4e4e08c8db05955cc00c4e1/575ca5ce34ac5d283b0502f9efc6408236868ea9/lib/python3.11/site-packages/streamlit/runtime/caching/cache_utils.py", line 260, in _get_or_create_cached_value
    return self._handle_cache_miss(cache, value_key, func_args, func_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/darren/Library/Caches/pex/venvs/0e7f7ef52d296012b4e4e08c8db05955cc00c4e1/575ca5ce34ac5d283b0502f9efc6408236868ea9/lib/python3.11/site-packages/streamlit/runtime/caching/cache_utils.py", line 318, in _handle_cache_miss
    computed_value = self._info.func(*func_args, **func_kwargs)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/darren/Library/Caches/pex/venvs/0e7f7ef52d296012b4e4e08c8db05955cc00c4e1/575ca5ce34ac5d283b0502f9efc6408236868ea9/lib/python3.11/site-packages/streamlit/runtime/connection_factory.py", line 81, in __create_connection
    return connection_class(connection_name=name, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/darren/Library/Caches/pex/venvs/0e7f7ef52d296012b4e4e08c8db05955cc00c4e1/575ca5ce34ac5d283b0502f9efc6408236868ea9/lib/python3.11/site-packages/streamlit/connections/base_connection.py", line 73, in __init__
    self._raw_instance: RawConnectionT | None = self._connect(**kwargs)
                                                ^^^^^^^^^^^^^^^^^^^^^^^
TypeError: GSheetsConnection._connect() got an unexpected keyword argument 'project_id'

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions