Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
darrenclark opened this issue Jan 30, 2025 · 1 comment

Comments

@darrenclark
Copy link

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'
@darrenclark
Copy link
Author

I'd be happy to submit a PR for this if that change makes sense!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant