Closed
Description
Environment details
- MacOs 10.15.4
- Python 3.7.9
- pybigquery 0.6.0
Steps to reproduce
Create an engine following the example authentication of the readme both for
- path credentials
- object credentials
Code example
from sqlalchemy import create_engine
from pybigquery.api import ApiClient
engine = create_engine(uri, credentials_info=secrets)
engine = create_engine(uri, credentials_path=secrets_path)
Stack trace
AttributeError Traceback (most recent call last)
<ipython-input-5-90cdb3af0bd1> in <module>
----> 1 engine = create_engine(uri, credentials_info=secrets)
~/.pyenv/versions/3.7.9/lib/python3.7/site-packages/sqlalchemy/engine/__init__.py in create_engine(*args, **kwargs)
523 strategy = kwargs.pop("strategy", default_strategy)
524 strategy = strategies.strategies[strategy]
--> 525 return strategy.create(*args, **kwargs)
526
527
~/.pyenv/versions/3.7.9/lib/python3.7/site-packages/sqlalchemy/engine/strategies.py in create(self, name_or_url, **kwargs)
96
97 # assemble connection arguments
---> 98 (cargs, cparams) = dialect.create_connect_args(u)
99 cparams.update(pop_kwarg("connect_args", {}))
100 cargs = list(cargs) # allow mutability
~/.pyenv/versions/3.7.9/lib/python3.7/site-packages/pybigquery/sqlalchemy_bigquery.py in create_connect_args(self, url)
365 project_id=project_id,
366 location=self.location,
--> 367 default_query_job_config=default_query_job_config,
368 )
369 return ([client], {})
~/.pyenv/versions/3.7.9/lib/python3.7/site-packages/pybigquery/_helpers.py in create_bigquery_client(credentials_info, credentials_path, default_query_job_config, location, project_id)
45 )
46 credentials = credentials.with_scopes(SCOPES)
---> 47 default_project = credentials.project
48 else:
49 credentials, default_project = google.auth.default(scopes=SCOPES)
AttributeError: 'Credentials' object has no attribute 'project'
Proposed Explanation
Both approaches above fail at accessing project
property of a Credentials
instance which does not exist (anymore?)
Proposed Solution
Right now I have monkey patched calls to _helpers.create_bigquery_client
this way:
from google.api_core import client_info
import google.auth
from google.cloud import bigquery
from google.oauth2 import service_account
from pybigquery._helpers import USER_AGENT_TEMPLATE, SCOPES, google_client_info
from pybigquery import _helpers
def _patched(
credentials_info=None,
credentials_path=None,
default_query_job_config=None,
location=None,
project_id=None,
):
default_project = None
if credentials_path:
credentials = service_account.Credentials.from_service_account_file(
credentials_path
)
credentials = credentials.with_scopes(SCOPES)
default_project = credentials.project_id
elif credentials_info:
credentials = service_account.Credentials.from_service_account_info(
credentials_info
)
credentials = credentials.with_scopes(SCOPES)
default_project = credentials.project_id
else:
credentials, default_project = google.auth.default(scopes=SCOPES)
if project_id is None:
project_id = default_project
return bigquery.Client(
client_info=google_client_info(),
project=project_id,
credentials=credentials,
location=location,
default_query_job_config=default_query_job_config,
)
_helpers.create_bigquery_client = _patched
engine = create_engine(uri, credentials_info=secrets)
The idea is to use credentials.project_id
instead of project
Thanks for any remark or help!